gmp plugin makes use of pkcs1/pgp/dnskey plugins
This commit is contained in:
@@ -26,7 +26,6 @@
|
|||||||
#include <asn1/oid.h>
|
#include <asn1/oid.h>
|
||||||
#include <asn1/asn1.h>
|
#include <asn1/asn1.h>
|
||||||
#include <asn1/asn1_parser.h>
|
#include <asn1/asn1_parser.h>
|
||||||
#include <pgp/pgp.h>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public exponent to use for key generation.
|
* Public exponent to use for key generation.
|
||||||
@@ -663,7 +662,7 @@ static gmp_rsa_private_key_t *generate(size_t key_size)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpz_init(t);
|
mpz_init(t);
|
||||||
mpz_init(n);
|
mpz_init(n);
|
||||||
mpz_init(d);
|
mpz_init(d);
|
||||||
mpz_init(exp1);
|
mpz_init(exp1);
|
||||||
@@ -724,48 +723,11 @@ static gmp_rsa_private_key_t *generate(size_t key_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASN.1 definition of a PKCS#1 RSA private key
|
* load private key from a RSA components
|
||||||
*/
|
*/
|
||||||
static const asn1Object_t privkeyObjects[] = {
|
static gmp_rsa_private_key_t *load(chunk_t n, chunk_t e, chunk_t d,
|
||||||
{ 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
|
chunk_t p, chunk_t q, chunk_t exp1, chunk_t exp2, chunk_t coeff)
|
||||||
{ 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
|
|
||||||
{ 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
|
|
||||||
{ 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
|
|
||||||
{ 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
|
|
||||||
{ 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
|
|
||||||
{ 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
|
|
||||||
{ 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
|
|
||||||
{ 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
|
|
||||||
{ 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
|
|
||||||
{ 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
|
|
||||||
ASN1_LOOP }, /* 10 */
|
|
||||||
{ 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
|
|
||||||
{ 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
|
|
||||||
{ 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
|
|
||||||
{ 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
|
|
||||||
{ 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 15 */
|
|
||||||
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
|
|
||||||
};
|
|
||||||
#define PRIV_KEY_VERSION 1
|
|
||||||
#define PRIV_KEY_MODULUS 2
|
|
||||||
#define PRIV_KEY_PUB_EXP 3
|
|
||||||
#define PRIV_KEY_PRIV_EXP 4
|
|
||||||
#define PRIV_KEY_PRIME1 5
|
|
||||||
#define PRIV_KEY_PRIME2 6
|
|
||||||
#define PRIV_KEY_EXP1 7
|
|
||||||
#define PRIV_KEY_EXP2 8
|
|
||||||
#define PRIV_KEY_COEFF 9
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load private key from a ASN1 encoded blob
|
|
||||||
*/
|
|
||||||
static gmp_rsa_private_key_t *load_asn1_der(chunk_t blob)
|
|
||||||
{
|
{
|
||||||
asn1_parser_t *parser;
|
|
||||||
chunk_t object;
|
|
||||||
int objectID ;
|
|
||||||
bool success = FALSE;
|
|
||||||
|
|
||||||
private_gmp_rsa_private_key_t *this = gmp_rsa_private_key_create_empty();
|
private_gmp_rsa_private_key_t *this = gmp_rsa_private_key_create_empty();
|
||||||
|
|
||||||
mpz_init(this->n);
|
mpz_init(this->n);
|
||||||
@@ -777,60 +739,31 @@ static gmp_rsa_private_key_t *load_asn1_der(chunk_t blob)
|
|||||||
mpz_init(this->exp2);
|
mpz_init(this->exp2);
|
||||||
mpz_init(this->coeff);
|
mpz_init(this->coeff);
|
||||||
|
|
||||||
parser = asn1_parser_create(privkeyObjects, blob);
|
mpz_import(this->n, n.len, 1, 1, 1, 0, n.ptr);
|
||||||
parser->set_flags(parser, FALSE, TRUE);
|
mpz_import(this->e, e.len, 1, 1, 1, 0, e.ptr);
|
||||||
|
mpz_import(this->d, d.len, 1, 1, 1, 0, d.ptr);
|
||||||
while (parser->iterate(parser, &objectID, &object))
|
mpz_import(this->p, p.len, 1, 1, 1, 0, p.ptr);
|
||||||
{
|
mpz_import(this->q, q.len, 1, 1, 1, 0, q.ptr);
|
||||||
switch (objectID)
|
mpz_import(this->coeff, coeff.len, 1, 1, 1, 0, coeff.ptr);
|
||||||
{
|
if (!exp1.len)
|
||||||
case PRIV_KEY_VERSION:
|
{ /* exp1 missing in key, recalculate: exp1 = d mod (p-1) */
|
||||||
if (object.len > 0 && *object.ptr != 0)
|
mpz_sub_ui(this->exp1, this->p, 1);
|
||||||
{
|
mpz_mod(this->exp1, this->d, this->exp1);
|
||||||
DBG1("PKCS#1 private key format is not version 1");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_MODULUS:
|
|
||||||
mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_PUB_EXP:
|
|
||||||
mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_PRIV_EXP:
|
|
||||||
mpz_import(this->d, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_PRIME1:
|
|
||||||
mpz_import(this->p, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_PRIME2:
|
|
||||||
mpz_import(this->q, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_EXP1:
|
|
||||||
mpz_import(this->exp1, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_EXP2:
|
|
||||||
mpz_import(this->exp2, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_COEFF:
|
|
||||||
mpz_import(this->coeff, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
success = parser->success(parser);
|
else
|
||||||
|
|
||||||
end:
|
|
||||||
parser->destroy(parser);
|
|
||||||
chunk_clear(&blob);
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
{
|
{
|
||||||
destroy(this);
|
mpz_import(this->exp1, exp1.len, 1, 1, 1, 0, exp1.ptr);
|
||||||
return NULL;
|
}
|
||||||
|
if (!exp2.len)
|
||||||
|
{ /* exp2 missing in key, recalculate: exp2 = d mod (q-1) */
|
||||||
|
mpz_sub_ui(this->exp2, this->q, 1);
|
||||||
|
mpz_mod(this->exp2, this->d, this->exp2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mpz_import(this->exp2, exp2.len, 1, 1, 1, 0, exp2.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
|
this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
|
||||||
|
|
||||||
if (!gmp_rsa_public_key_build_id(this->n, this->e,
|
if (!gmp_rsa_public_key_build_id(this->n, this->e,
|
||||||
&this->keyid, &this->keyid_info))
|
&this->keyid, &this->keyid_info))
|
||||||
{
|
{
|
||||||
@@ -845,138 +778,6 @@ end:
|
|||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* load private key from an OpenPGP blob coded according to section
|
|
||||||
*/
|
|
||||||
static gmp_rsa_private_key_t *load_pgp(chunk_t blob)
|
|
||||||
{
|
|
||||||
mpz_t u;
|
|
||||||
int objectID;
|
|
||||||
chunk_t packet = blob;
|
|
||||||
private_gmp_rsa_private_key_t *this = gmp_rsa_private_key_create_empty();
|
|
||||||
|
|
||||||
mpz_init(this->n);
|
|
||||||
mpz_init(this->e);
|
|
||||||
mpz_init(this->p);
|
|
||||||
mpz_init(this->q);
|
|
||||||
mpz_init(this->d);
|
|
||||||
mpz_init(this->exp1);
|
|
||||||
mpz_init(this->exp2);
|
|
||||||
mpz_init(this->coeff);
|
|
||||||
|
|
||||||
for (objectID = PRIV_KEY_MODULUS; objectID <= PRIV_KEY_COEFF; objectID++)
|
|
||||||
{
|
|
||||||
chunk_t object;
|
|
||||||
|
|
||||||
switch (objectID)
|
|
||||||
{
|
|
||||||
case PRIV_KEY_PRIV_EXP:
|
|
||||||
{
|
|
||||||
pgp_sym_alg_t s2k;
|
|
||||||
|
|
||||||
/* string-to-key usage */
|
|
||||||
s2k = pgp_length(&packet, 1);
|
|
||||||
DBG2("L3 - string-to-key: %d", s2k);
|
|
||||||
|
|
||||||
if (s2k == 255 || s2k == 254)
|
|
||||||
{
|
|
||||||
DBG1("string-to-key specifiers not supported");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
DBG2(" %N", pgp_sym_alg_names, s2k);
|
|
||||||
|
|
||||||
if (s2k != PGP_SYM_ALG_PLAIN)
|
|
||||||
{
|
|
||||||
DBG1("%N encryption not supported", pgp_sym_alg_names, s2k);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case PRIV_KEY_EXP1:
|
|
||||||
case PRIV_KEY_EXP2:
|
|
||||||
/* not contained in OpenPGP secret key payload */
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DBG2("L3 - %s:", privkeyObjects[objectID].name);
|
|
||||||
object.len = pgp_length(&packet, 2);
|
|
||||||
|
|
||||||
if (object.len == PGP_INVALID_LENGTH)
|
|
||||||
{
|
|
||||||
DBG1("OpenPGP length is invalid");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
object.len = (object.len + 7) / BITS_PER_BYTE;
|
|
||||||
if (object.len > packet.len)
|
|
||||||
{
|
|
||||||
DBG1("OpenPGP field is too short");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
object.ptr = packet.ptr;
|
|
||||||
packet.ptr += object.len;
|
|
||||||
packet.len -= object.len;
|
|
||||||
DBG4("%B", &object);
|
|
||||||
|
|
||||||
switch (objectID)
|
|
||||||
{
|
|
||||||
case PRIV_KEY_MODULUS:
|
|
||||||
mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_PUB_EXP:
|
|
||||||
mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_PRIV_EXP:
|
|
||||||
mpz_import(this->d, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_PRIME1:
|
|
||||||
mpz_import(this->q, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_PRIME2:
|
|
||||||
mpz_import(this->p, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PRIV_KEY_COEFF:
|
|
||||||
mpz_import(this->coeff, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* auxiliary variable */
|
|
||||||
mpz_init(u);
|
|
||||||
|
|
||||||
/* exp1 = d mod (p-1) */
|
|
||||||
mpz_sub_ui(u, this->p, 1);
|
|
||||||
mpz_mod(this->exp1, this->d, u);
|
|
||||||
|
|
||||||
/* exp2 = d mod (q-1) */
|
|
||||||
mpz_sub_ui(u, this->q, 1);
|
|
||||||
mpz_mod(this->exp2, this->d, u);
|
|
||||||
|
|
||||||
mpz_clear(u);
|
|
||||||
chunk_clear(&blob);
|
|
||||||
|
|
||||||
this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
|
|
||||||
|
|
||||||
if (!gmp_rsa_public_key_build_id(this->n, this->e,
|
|
||||||
&this->keyid, &this->keyid_info))
|
|
||||||
{
|
|
||||||
destroy(this);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (check(this) != SUCCESS)
|
|
||||||
{
|
|
||||||
destroy(this);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return &this->public;
|
|
||||||
|
|
||||||
end:
|
|
||||||
chunk_clear(&blob);
|
|
||||||
destroy(this);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct private_builder_t private_builder_t;
|
typedef struct private_builder_t private_builder_t;
|
||||||
/**
|
/**
|
||||||
* Builder implementation for key loading/generation
|
* Builder implementation for key loading/generation
|
||||||
@@ -984,8 +785,10 @@ typedef struct private_builder_t private_builder_t;
|
|||||||
struct private_builder_t {
|
struct private_builder_t {
|
||||||
/** implements the builder interface */
|
/** implements the builder interface */
|
||||||
builder_t public;
|
builder_t public;
|
||||||
/** loaded/generated private key */
|
/** key size, if generating */
|
||||||
gmp_rsa_private_key_t *key;
|
u_int key_size;
|
||||||
|
/** rsa key parameters */
|
||||||
|
chunk_t n, e, d, p, q, exp1, exp2, coeff;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -993,8 +796,17 @@ struct private_builder_t {
|
|||||||
*/
|
*/
|
||||||
static gmp_rsa_private_key_t *build(private_builder_t *this)
|
static gmp_rsa_private_key_t *build(private_builder_t *this)
|
||||||
{
|
{
|
||||||
gmp_rsa_private_key_t *key = this->key;
|
gmp_rsa_private_key_t *key = NULL;
|
||||||
|
|
||||||
|
if (this->key_size)
|
||||||
|
{
|
||||||
|
key = generate(this->key_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
key = load(this->n, this->e, this->d, this->p, this->q,
|
||||||
|
this->exp1, this->exp2, this->coeff);
|
||||||
|
}
|
||||||
free(this);
|
free(this);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
@@ -1004,45 +816,43 @@ static gmp_rsa_private_key_t *build(private_builder_t *this)
|
|||||||
*/
|
*/
|
||||||
static void add(private_builder_t *this, builder_part_t part, ...)
|
static void add(private_builder_t *this, builder_part_t part, ...)
|
||||||
{
|
{
|
||||||
if (!this->key)
|
va_list args;
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
chunk_t chunk;
|
|
||||||
|
|
||||||
switch (part)
|
va_start(args, part);
|
||||||
{
|
switch (part)
|
||||||
case BUILD_BLOB_ASN1_DER:
|
|
||||||
{
|
|
||||||
va_start(args, part);
|
|
||||||
chunk = va_arg(args, chunk_t);
|
|
||||||
this->key = load_asn1_der(chunk_clone(chunk));
|
|
||||||
va_end(args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case BUILD_BLOB_PGP:
|
|
||||||
{
|
|
||||||
va_start(args, part);
|
|
||||||
chunk = va_arg(args, chunk_t);
|
|
||||||
this->key = load_pgp(chunk_clone(chunk));
|
|
||||||
va_end(args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case BUILD_KEY_SIZE:
|
|
||||||
{
|
|
||||||
va_start(args, part);
|
|
||||||
this->key = generate(va_arg(args, u_int));
|
|
||||||
va_end(args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this->key)
|
|
||||||
{
|
{
|
||||||
destroy((private_gmp_rsa_private_key_t*)this->key);
|
case BUILD_KEY_SIZE:
|
||||||
|
this->key_size = va_arg(args, u_int);
|
||||||
|
return;
|
||||||
|
case BUILD_RSA_MODULUS:
|
||||||
|
this->n = va_arg(args, chunk_t);
|
||||||
|
break;
|
||||||
|
case BUILD_RSA_PUB_EXP:
|
||||||
|
this->e = va_arg(args, chunk_t);
|
||||||
|
break;
|
||||||
|
case BUILD_RSA_PRIV_EXP:
|
||||||
|
this->d = va_arg(args, chunk_t);
|
||||||
|
break;
|
||||||
|
case BUILD_RSA_PRIME1:
|
||||||
|
this->p = va_arg(args, chunk_t);
|
||||||
|
break;
|
||||||
|
case BUILD_RSA_PRIME2:
|
||||||
|
this->q = va_arg(args, chunk_t);
|
||||||
|
break;
|
||||||
|
case BUILD_RSA_EXP1:
|
||||||
|
this->exp1 = va_arg(args, chunk_t);
|
||||||
|
break;
|
||||||
|
case BUILD_RSA_EXP2:
|
||||||
|
this->exp1 = va_arg(args, chunk_t);
|
||||||
|
break;
|
||||||
|
case BUILD_RSA_COEFF:
|
||||||
|
this->coeff = va_arg(args, chunk_t);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
builder_cancel(&this->public);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
builder_cancel(&this->public);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1059,7 +869,9 @@ builder_t *gmp_rsa_private_key_builder(key_type_t type)
|
|||||||
|
|
||||||
this = malloc_thing(private_builder_t);
|
this = malloc_thing(private_builder_t);
|
||||||
|
|
||||||
this->key = NULL;
|
this->n = this->e = this->d = this->p = this->q = chunk_empty;
|
||||||
|
this->exp1 = this->exp2 = this->coeff = chunk_empty;
|
||||||
|
this->key_size = 0;
|
||||||
this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
|
this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
|
||||||
this->public.build = (void*(*)(builder_t *this))build;
|
this->public.build = (void*(*)(builder_t *this))build;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2005-2008 Martin Willi
|
* Copyright (C) 2005-2009 Martin Willi
|
||||||
* Copyright (C) 2005 Jan Hutter
|
* Copyright (C) 2005 Jan Hutter
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
@@ -27,7 +27,6 @@
|
|||||||
#include <asn1/asn1.h>
|
#include <asn1/asn1.h>
|
||||||
#include <asn1/asn1_parser.h>
|
#include <asn1/asn1_parser.h>
|
||||||
#include <crypto/hashers/hasher.h>
|
#include <crypto/hashers/hasher.h>
|
||||||
#include <pgp/pgp.h>
|
|
||||||
|
|
||||||
typedef struct private_gmp_rsa_public_key_t private_gmp_rsa_public_key_t;
|
typedef struct private_gmp_rsa_public_key_t private_gmp_rsa_public_key_t;
|
||||||
|
|
||||||
@@ -590,59 +589,19 @@ gmp_rsa_public_key_t *gmp_rsa_public_key_create_from_n_e(mpz_t n, mpz_t e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ASN.1 definition of RSApublicKey
|
* Load a public key from n and e
|
||||||
*/
|
*/
|
||||||
static const asn1Object_t pubkeyObjects[] = {
|
static gmp_rsa_public_key_t *load(chunk_t n, chunk_t e)
|
||||||
{ 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
|
|
||||||
{ 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
|
|
||||||
{ 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
|
|
||||||
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
|
|
||||||
};
|
|
||||||
#define PUB_KEY_RSA_PUBLIC_KEY 0
|
|
||||||
#define PUB_KEY_MODULUS 1
|
|
||||||
#define PUB_KEY_EXPONENT 2
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a public key from an ASN.1 encoded blob
|
|
||||||
*/
|
|
||||||
static gmp_rsa_public_key_t *load_asn1_der(chunk_t blob)
|
|
||||||
{
|
{
|
||||||
asn1_parser_t *parser;
|
|
||||||
chunk_t object;
|
|
||||||
int objectID;
|
|
||||||
bool success = FALSE;
|
|
||||||
|
|
||||||
private_gmp_rsa_public_key_t *this = gmp_rsa_public_key_create_empty();
|
private_gmp_rsa_public_key_t *this = gmp_rsa_public_key_create_empty();
|
||||||
|
|
||||||
mpz_init(this->n);
|
mpz_init(this->n);
|
||||||
mpz_init(this->e);
|
mpz_init(this->e);
|
||||||
|
|
||||||
parser = asn1_parser_create(pubkeyObjects, blob);
|
mpz_import(this->n, n.len, 1, 1, 1, 0, n.ptr);
|
||||||
|
mpz_import(this->e, e.len, 1, 1, 1, 0, e.ptr);
|
||||||
while (parser->iterate(parser, &objectID, &object))
|
|
||||||
{
|
|
||||||
switch (objectID)
|
|
||||||
{
|
|
||||||
case PUB_KEY_MODULUS:
|
|
||||||
mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PUB_KEY_EXPONENT:
|
|
||||||
mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
success = parser->success(parser);
|
|
||||||
free(blob.ptr);
|
|
||||||
parser->destroy(parser);
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
destroy(this);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
|
this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
|
||||||
|
|
||||||
if (!gmp_rsa_public_key_build_id(this->n, this->e,
|
if (!gmp_rsa_public_key_build_id(this->n, this->e,
|
||||||
&this->keyid, &this->keyid_info))
|
&this->keyid, &this->keyid_info))
|
||||||
{
|
{
|
||||||
@@ -652,142 +611,16 @@ static gmp_rsa_public_key_t *load_asn1_der(chunk_t blob)
|
|||||||
return &this->public;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a public key from an OpenPGP blob
|
|
||||||
*/
|
|
||||||
static gmp_rsa_public_key_t* load_pgp(chunk_t blob)
|
|
||||||
{
|
|
||||||
int objectID;
|
|
||||||
chunk_t packet = blob;
|
|
||||||
private_gmp_rsa_public_key_t *this = gmp_rsa_public_key_create_empty();
|
|
||||||
|
|
||||||
mpz_init(this->n);
|
|
||||||
mpz_init(this->e);
|
|
||||||
|
|
||||||
for (objectID = PUB_KEY_MODULUS; objectID <= PUB_KEY_EXPONENT; objectID++)
|
|
||||||
{
|
|
||||||
chunk_t object;
|
|
||||||
|
|
||||||
DBG2("L3 - %s:", pubkeyObjects[objectID].name);
|
|
||||||
object.len = pgp_length(&packet, 2);
|
|
||||||
|
|
||||||
if (object.len == PGP_INVALID_LENGTH)
|
|
||||||
{
|
|
||||||
DBG1("OpenPGP length is invalid");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
object.len = (object.len + 7) / BITS_PER_BYTE;
|
|
||||||
if (object.len > packet.len)
|
|
||||||
{
|
|
||||||
DBG1("OpenPGP field is too short");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
object.ptr = packet.ptr;
|
|
||||||
packet.ptr += object.len;
|
|
||||||
packet.len -= object.len;
|
|
||||||
DBG4("%B", &object);
|
|
||||||
|
|
||||||
switch (objectID)
|
|
||||||
{
|
|
||||||
case PUB_KEY_MODULUS:
|
|
||||||
mpz_import(this->n, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
case PUB_KEY_EXPONENT:
|
|
||||||
mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
|
|
||||||
free(blob.ptr);
|
|
||||||
|
|
||||||
if (!gmp_rsa_public_key_build_id(this->n, this->e,
|
|
||||||
&this->keyid, &this->keyid_info))
|
|
||||||
{
|
|
||||||
destroy(this);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return &this->public;
|
|
||||||
|
|
||||||
end:
|
|
||||||
free(blob.ptr);
|
|
||||||
destroy(this);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load a public key from an RFC 3110 encoded blob
|
|
||||||
*/
|
|
||||||
static gmp_rsa_public_key_t *load_rfc_3110(chunk_t blob)
|
|
||||||
{
|
|
||||||
chunk_t exponent, modulus;
|
|
||||||
u_char *pos = blob.ptr;
|
|
||||||
size_t len = blob.len;
|
|
||||||
private_gmp_rsa_public_key_t *this = gmp_rsa_public_key_create_empty();
|
|
||||||
|
|
||||||
mpz_init(this->n);
|
|
||||||
mpz_init(this->e);
|
|
||||||
|
|
||||||
if (blob.len < 3)
|
|
||||||
{
|
|
||||||
DBG1("RFC 3110 public key blob too short for exponent length");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
if (pos[0] != 0x00)
|
|
||||||
{
|
|
||||||
exponent = chunk_create(pos + 1, pos[0]);
|
|
||||||
pos++;
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
exponent = chunk_create(pos + 3, 256*pos[1] + pos[2]);
|
|
||||||
pos += 3;
|
|
||||||
len -= 3;
|
|
||||||
}
|
|
||||||
if (exponent.len > len)
|
|
||||||
{
|
|
||||||
DBG1("RFC 3110 public key blob too short for exponent");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
pos += exponent.len;
|
|
||||||
len -= exponent.len;
|
|
||||||
|
|
||||||
if (len == 0)
|
|
||||||
{
|
|
||||||
DBG1("RFC 3110 public key blob has zero length modulus");
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
modulus = chunk_create(pos, len);
|
|
||||||
|
|
||||||
mpz_import(this->n, modulus.len, 1, 1, 1, 0, modulus.ptr);
|
|
||||||
mpz_import(this->e, exponent.len, 1, 1, 1, 0, exponent.ptr);
|
|
||||||
this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
|
|
||||||
free(blob.ptr);
|
|
||||||
|
|
||||||
if (!gmp_rsa_public_key_build_id(this->n, this->e,
|
|
||||||
&this->keyid, &this->keyid_info))
|
|
||||||
{
|
|
||||||
destroy(this);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return &this->public;
|
|
||||||
|
|
||||||
end:
|
|
||||||
free(blob.ptr);
|
|
||||||
destroy(this);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct private_builder_t private_builder_t;
|
typedef struct private_builder_t private_builder_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder implementation for key loading
|
* Builder implementation for key loading
|
||||||
*/
|
*/
|
||||||
struct private_builder_t {
|
struct private_builder_t {
|
||||||
/** implements the builder interface */
|
/** implements the builder interface */
|
||||||
builder_t public;
|
builder_t public;
|
||||||
/** loaded public key */
|
/** rsa key parameters */
|
||||||
gmp_rsa_public_key_t *key;
|
chunk_t n, e;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -795,8 +628,9 @@ struct private_builder_t {
|
|||||||
*/
|
*/
|
||||||
static gmp_rsa_public_key_t *build(private_builder_t *this)
|
static gmp_rsa_public_key_t *build(private_builder_t *this)
|
||||||
{
|
{
|
||||||
gmp_rsa_public_key_t *key = this->key;
|
gmp_rsa_public_key_t *key;
|
||||||
|
|
||||||
|
key = load(this->n, this->e);
|
||||||
free(this);
|
free(this);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
@@ -806,46 +640,22 @@ static gmp_rsa_public_key_t *build(private_builder_t *this)
|
|||||||
*/
|
*/
|
||||||
static void add(private_builder_t *this, builder_part_t part, ...)
|
static void add(private_builder_t *this, builder_part_t part, ...)
|
||||||
{
|
{
|
||||||
if (!this->key)
|
va_list args;
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
chunk_t chunk;
|
|
||||||
|
|
||||||
switch (part)
|
va_start(args, part);
|
||||||
{
|
switch (part)
|
||||||
case BUILD_BLOB_ASN1_DER:
|
|
||||||
{
|
|
||||||
va_start(args, part);
|
|
||||||
chunk = va_arg(args, chunk_t);
|
|
||||||
this->key = load_asn1_der(chunk_clone(chunk));
|
|
||||||
va_end(args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case BUILD_BLOB_PGP:
|
|
||||||
{
|
|
||||||
va_start(args, part);
|
|
||||||
chunk = va_arg(args, chunk_t);
|
|
||||||
this->key = load_pgp(chunk_clone(chunk));
|
|
||||||
va_end(args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case BUILD_BLOB_DNSKEY:
|
|
||||||
{
|
|
||||||
va_start(args, part);
|
|
||||||
chunk = va_arg(args, chunk_t);
|
|
||||||
this->key = load_rfc_3110(chunk_clone(chunk));
|
|
||||||
va_end(args);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this->key)
|
|
||||||
{
|
{
|
||||||
destroy((private_gmp_rsa_public_key_t*)this->key);
|
case BUILD_RSA_MODULUS:
|
||||||
|
this->n = va_arg(args, chunk_t);
|
||||||
|
break;
|
||||||
|
case BUILD_RSA_PUB_EXP:
|
||||||
|
this->e = va_arg(args, chunk_t);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
builder_cancel(&this->public);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
builder_cancel(&this->public);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -862,7 +672,7 @@ builder_t *gmp_rsa_public_key_builder(key_type_t type)
|
|||||||
|
|
||||||
this = malloc_thing(private_builder_t);
|
this = malloc_thing(private_builder_t);
|
||||||
|
|
||||||
this->key = NULL;
|
this->n = this->e = chunk_empty;
|
||||||
this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
|
this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
|
||||||
this->public.build = (void*(*)(builder_t *this))build;
|
this->public.build = (void*(*)(builder_t *this))build;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user