refactoring of the ASN.1 parser
This commit is contained in:
@@ -18,8 +18,10 @@
|
||||
|
||||
#include "gmp_public_key.h"
|
||||
|
||||
#include <asn1/asn1.h>
|
||||
#include <debug.h>
|
||||
#include <asn1/oid.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/asn1_parser.h>
|
||||
|
||||
/**
|
||||
* ASN.1 definition of a subjectPublicKeyInfo structure
|
||||
@@ -27,67 +29,64 @@
|
||||
static const asn1Object_t pkinfoObjects[] = {
|
||||
{ 0, "subjectPublicKeyInfo",ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
|
||||
{ 1, "algorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
|
||||
{ 1, "subjectPublicKey", ASN1_BIT_STRING, ASN1_NONE }, /* 2 */
|
||||
{ 2, "publicKey", ASN1_SEQUENCE, ASN1_RAW }, /* 3 */
|
||||
{ 1, "subjectPublicKey", ASN1_BIT_STRING, ASN1_OBJ }, /* 2 */
|
||||
};
|
||||
#define PKINFO 0
|
||||
#define PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM 1
|
||||
#define PKINFO_SUBJECT_PUBLIC_KEY 2
|
||||
#define PKINFO_PUBLIC_KEY 3
|
||||
#define PKINFO_ROOF 4
|
||||
#define PKINFO_ROOF 3
|
||||
|
||||
/**
|
||||
* Load a public key from an ASN1 encoded blob
|
||||
*/
|
||||
static public_key_t *load(chunk_t blob)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
chunk_t object, data = chunk_empty;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
asn1_parser_t *parser;
|
||||
chunk_t object;
|
||||
int objectID;
|
||||
public_key_t *key = NULL;
|
||||
key_type_t type = KEY_ANY;
|
||||
|
||||
parser = asn1_parser_create(pkinfoObjects, PKINFO_ROOF, blob);
|
||||
|
||||
asn1_init(&ctx, blob, 0, FALSE, FALSE);
|
||||
|
||||
while (objectID < PKINFO_ROOF)
|
||||
while (parser->iterate(parser, &objectID, &object))
|
||||
{
|
||||
if (!extract_object(pkinfoObjects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
free(blob.ptr);
|
||||
return NULL;
|
||||
}
|
||||
switch (objectID)
|
||||
{
|
||||
case PKINFO_SUBJECT_PUBLIC_KEY_ALGORITHM:
|
||||
switch (parse_algorithmIdentifier(object, level, NULL))
|
||||
{
|
||||
int oid = asn1_parse_algorithmIdentifier(object,
|
||||
parser->get_level(parser)+1, NULL);
|
||||
|
||||
if (oid == OID_RSA_ENCRYPTION)
|
||||
{
|
||||
case OID_RSA_ENCRYPTION:
|
||||
type = KEY_RSA;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
type = KEY_RSA;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* key type not supported */
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PKINFO_SUBJECT_PUBLIC_KEY:
|
||||
if (ctx.blobs[2].len > 0 && *ctx.blobs[2].ptr == 0x00)
|
||||
{ /* skip initial bit string octet defining 0 unused bits */
|
||||
ctx.blobs[2].ptr++; ctx.blobs[2].len--;
|
||||
if (object.len > 0 && *object.ptr == 0x00)
|
||||
{
|
||||
/* skip initial bit string octet defining 0 unused bits */
|
||||
object.ptr++;
|
||||
object.len--;
|
||||
key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
|
||||
BUILD_BLOB_ASN1_DER,
|
||||
chunk_clone(object),
|
||||
BUILD_END);
|
||||
}
|
||||
break;
|
||||
case PKINFO_PUBLIC_KEY:
|
||||
data = chunk_clone(object);
|
||||
break;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
parser->destroy(parser);
|
||||
free(blob.ptr);
|
||||
if (type == KEY_ANY)
|
||||
{
|
||||
free(data.ptr);
|
||||
return NULL;
|
||||
}
|
||||
return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, type,
|
||||
BUILD_BLOB_ASN1_DER, data, BUILD_END);
|
||||
return key;
|
||||
}
|
||||
|
||||
typedef struct private_builder_t private_builder_t;
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
#include "gmp_rsa_public_key.h"
|
||||
|
||||
#include <debug.h>
|
||||
#include <asn1/oid.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/asn1_parser.h>
|
||||
|
||||
/**
|
||||
* Public exponent to use for key generation.
|
||||
@@ -109,8 +111,10 @@ struct private_gmp_rsa_private_key_t {
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
/* ASN.1 definition of a PKCS#1 RSA private key */
|
||||
static const asn1Object_t privkey_objects[] = {
|
||||
/**
|
||||
* ASN.1 definition of a PKCS#1 RSA private key
|
||||
*/
|
||||
static const asn1Object_t privkeyObjects[] = {
|
||||
{ 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
|
||||
{ 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
|
||||
{ 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
|
||||
@@ -673,10 +677,11 @@ static gmp_rsa_private_key_t *generate(size_t key_size)
|
||||
*/
|
||||
static gmp_rsa_private_key_t *load(chunk_t blob)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
asn1_parser_t *parser;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
int objectID ;
|
||||
bool success = TRUE;
|
||||
|
||||
private_gmp_rsa_private_key_t *this = gmp_rsa_private_key_create_empty();
|
||||
|
||||
mpz_init(this->n);
|
||||
@@ -688,24 +693,17 @@ static gmp_rsa_private_key_t *load(chunk_t blob)
|
||||
mpz_init(this->exp2);
|
||||
mpz_init(this->coeff);
|
||||
|
||||
asn1_init(&ctx, blob, 0, FALSE, TRUE);
|
||||
parser = asn1_parser_create(privkeyObjects, PRIV_KEY_ROOF, blob);
|
||||
parser->set_flags(parser, FALSE, TRUE);
|
||||
|
||||
while (objectID < PRIV_KEY_ROOF)
|
||||
while (parser->iterate(parser, &objectID, &object))
|
||||
{
|
||||
if (!extract_object(privkey_objects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
chunk_clear(&blob);
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
switch (objectID)
|
||||
{
|
||||
case PRIV_KEY_VERSION:
|
||||
if (object.len > 0 && *object.ptr != 0)
|
||||
{
|
||||
chunk_clear(&blob);
|
||||
destroy(this);
|
||||
return NULL;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
case PRIV_KEY_MODULUS:
|
||||
@@ -733,18 +731,28 @@ static gmp_rsa_private_key_t *load(chunk_t blob)
|
||||
mpz_import(this->coeff, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
|
||||
end:
|
||||
success &= parser->success(parser);
|
||||
parser->destroy(parser);
|
||||
chunk_clear(&blob);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -25,35 +25,38 @@
|
||||
#include "gmp_rsa_public_key.h"
|
||||
|
||||
#include <debug.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
#include <asn1/oid.h>
|
||||
#include <asn1/asn1.h>
|
||||
#include <asn1/asn1_parser.h>
|
||||
#include <asn1/pem.h>
|
||||
#include <crypto/hashers/hasher.h>
|
||||
|
||||
/**
|
||||
* defined in gmp_rsa_private_key.c
|
||||
*/
|
||||
extern chunk_t gmp_mpz_to_asn1(const mpz_t value);
|
||||
|
||||
|
||||
/* ASN.1 definition of RSApublicKey */
|
||||
/**
|
||||
* ASN.1 definition of RSApublicKey
|
||||
*/
|
||||
static const asn1Object_t pubkeyObjects[] = {
|
||||
{ 0, "RSAPublicKey", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
|
||||
{ 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 1 */
|
||||
{ 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 2 */
|
||||
};
|
||||
|
||||
#define PUB_KEY_RSA_PUBLIC_KEY 0
|
||||
#define PUB_KEY_MODULUS 1
|
||||
#define PUB_KEY_EXPONENT 2
|
||||
#define PUB_KEY_ROOF 3
|
||||
|
||||
/* ASN.1 definition of digestInfo */
|
||||
/**
|
||||
* ASN.1 definition of digestInfo
|
||||
*/
|
||||
static const asn1Object_t digestInfoObjects[] = {
|
||||
{ 0, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
|
||||
{ 1, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */
|
||||
{ 1, "digest", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
|
||||
};
|
||||
|
||||
#define DIGEST_INFO 0
|
||||
#define DIGEST_INFO_ALGORITHM 1
|
||||
#define DIGEST_INFO_DIGEST 2
|
||||
@@ -141,7 +144,7 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
|
||||
chunk_t data, chunk_t signature)
|
||||
{
|
||||
chunk_t em_ori, em;
|
||||
bool res = FALSE;
|
||||
bool success = FALSE;
|
||||
|
||||
/* remove any preceding 0-bytes from signature */
|
||||
while (signature.len && *(signature.ptr) == 0x00)
|
||||
@@ -199,20 +202,15 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
|
||||
|
||||
/* parse ASN.1-based digestInfo */
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
asn1_parser_t *parser;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
int objectID;
|
||||
hash_algorithm_t hash_algorithm = HASH_UNKNOWN;
|
||||
|
||||
asn1_init(&ctx, em, 0, FALSE, FALSE);
|
||||
parser = asn1_parser_create(digestInfoObjects, DIGEST_INFO_ROOF, em);
|
||||
|
||||
while (objectID < DIGEST_INFO_ROOF)
|
||||
while (parser->iterate(parser, &objectID, &object))
|
||||
{
|
||||
if (!extract_object(digestInfoObjects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
switch (objectID)
|
||||
{
|
||||
case DIGEST_INFO:
|
||||
@@ -221,20 +219,21 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
|
||||
{
|
||||
DBG1("digestInfo field in signature is followed by %u surplus bytes",
|
||||
em.len - object.len);
|
||||
goto end;
|
||||
goto end_parser;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIGEST_INFO_ALGORITHM:
|
||||
{
|
||||
int hash_oid = parse_algorithmIdentifier(object, level+1, NULL);
|
||||
int hash_oid = asn1_parse_algorithmIdentifier(object,
|
||||
parser->get_level(parser)+1, NULL);
|
||||
|
||||
hash_algorithm = hasher_algorithm_from_oid(hash_oid);
|
||||
if (hash_algorithm == HASH_UNKNOWN ||
|
||||
(algorithm != HASH_UNKNOWN && hash_algorithm != algorithm))
|
||||
{
|
||||
DBG1("wrong hash algorithm used in signature");
|
||||
goto end;
|
||||
goto end_parser;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -248,7 +247,7 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
|
||||
{
|
||||
DBG1("hash algorithm %N not supported",
|
||||
hash_algorithm_names, hash_algorithm);
|
||||
goto end;
|
||||
goto end_parser;
|
||||
}
|
||||
|
||||
if (object.len != hasher->get_hash_size(hasher))
|
||||
@@ -256,26 +255,29 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
|
||||
DBG1("hash size in signature is %u bytes instead of %u "
|
||||
"bytes", object.len, hasher->get_hash_size(hasher));
|
||||
hasher->destroy(hasher);
|
||||
goto end;
|
||||
goto end_parser;
|
||||
}
|
||||
|
||||
/* build our own hash and compare */
|
||||
hasher->allocate_hash(hasher, data, &hash);
|
||||
hasher->destroy(hasher);
|
||||
res = memeq(object.ptr, hash.ptr, hash.len);
|
||||
success = memeq(object.ptr, hash.ptr, hash.len);
|
||||
free(hash.ptr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
|
||||
end_parser:
|
||||
success &= parser->success(parser);
|
||||
parser->destroy(parser);
|
||||
}
|
||||
|
||||
end:
|
||||
free(em_ori.ptr);
|
||||
return res;
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -465,25 +467,20 @@ gmp_rsa_public_key_t *gmp_rsa_public_key_create_from_n_e(mpz_t n, mpz_t e)
|
||||
*/
|
||||
static gmp_rsa_public_key_t *load(chunk_t blob)
|
||||
{
|
||||
asn1_ctx_t ctx;
|
||||
asn1_parser_t *parser;
|
||||
chunk_t object;
|
||||
u_int level;
|
||||
int objectID = 0;
|
||||
int objectID;
|
||||
bool success;
|
||||
|
||||
private_gmp_rsa_public_key_t *this = gmp_rsa_public_key_create_empty();
|
||||
|
||||
mpz_init(this->n);
|
||||
mpz_init(this->e);
|
||||
|
||||
asn1_init(&ctx, blob, 0, FALSE, FALSE);
|
||||
parser = asn1_parser_create(pubkeyObjects, PUB_KEY_ROOF, blob);
|
||||
|
||||
while (objectID < PUB_KEY_ROOF)
|
||||
while (parser->iterate(parser, &objectID, &object))
|
||||
{
|
||||
if (!extract_object(pubkeyObjects, &objectID, &object, &level, &ctx))
|
||||
{
|
||||
free(blob.ptr);
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
switch (objectID)
|
||||
{
|
||||
case PUB_KEY_MODULUS:
|
||||
@@ -493,10 +490,20 @@ static gmp_rsa_public_key_t *load(chunk_t blob)
|
||||
mpz_import(this->e, object.len, 1, 1, 1, 0, object.ptr);
|
||||
break;
|
||||
}
|
||||
objectID++;
|
||||
}
|
||||
|
||||
free(blob.ptr);
|
||||
success = parser->success(parser);
|
||||
parser->destroy(parser);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this->k = (mpz_sizeinbase(this->n, 2) + 7) / 8;
|
||||
|
||||
if (!gmp_rsa_public_key_build_id(this->n, this->e,
|
||||
&this->keyid, &this->keyid_info))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user