RSA and DSA public keys are stored using the SubjectPublicKeyInfo format.

This commit is contained in:
Nikos Mavrogiannopoulos 2011-03-21 19:24:10 +01:00 committed by Steffen Jaeckel
parent 8c2850f8d9
commit fa22e791d4
13 changed files with 551 additions and 61 deletions

View File

@ -143,6 +143,7 @@ src/mac/xcbc/xcbc_file.o src/mac/xcbc/xcbc_init.o src/mac/xcbc/xcbc_memory.o \
src/mac/xcbc/xcbc_memory_multi.o src/mac/xcbc/xcbc_process.o src/mac/xcbc/xcbc_test.o \
src/math/fp/ltc_ecc_fp_mulmod.o src/math/gmp_desc.o src/math/ltm_desc.o src/math/multi.o \
src/math/rand_prime.o src/math/tfm_desc.o src/misc/base64/base64_decode.o \
src/misc/pk_get_oid.o \
src/misc/base64/base64_encode.o src/misc/burn_stack.o src/misc/crypt/crypt_argchk.o \
src/misc/crypt/crypt.o src/misc/crypt/crypt_cipher_descriptor.o src/misc/crypt/crypt_cipher_is_valid.o \
src/misc/crypt/crypt_find_cipher_any.o src/misc/crypt/crypt_find_cipher.o \
@ -173,6 +174,7 @@ src/modes/xts/xts_decrypt.o src/modes/xts/xts_done.o src/modes/xts/xts_encrypt.o
src/modes/xts/xts_init.o src/modes/xts/xts_mult_x.o src/modes/xts/xts_test.o \
src/pk/asn1/der/bit/der_decode_bit_string.o src/pk/asn1/der/bit/der_encode_bit_string.o \
src/pk/asn1/der/bit/der_length_bit_string.o src/pk/asn1/der/boolean/der_decode_boolean.o \
src/pk/asn1/der/bit/der_decode_raw_bit_string.o src/pk/asn1/der/bit/der_encode_raw_bit_string.o \
src/pk/asn1/der/boolean/der_encode_boolean.o src/pk/asn1/der/boolean/der_length_boolean.o \
src/pk/asn1/der/choice/der_decode_choice.o src/pk/asn1/der/ia5/der_decode_ia5_string.o \
src/pk/asn1/der/ia5/der_encode_ia5_string.o src/pk/asn1/der/ia5/der_length_ia5_string.o \
@ -186,6 +188,8 @@ src/pk/asn1/der/octet/der_length_octet_string.o \
src/pk/asn1/der/printable_string/der_decode_printable_string.o \
src/pk/asn1/der/printable_string/der_encode_printable_string.o \
src/pk/asn1/der/printable_string/der_length_printable_string.o \
src/pk/asn1/der/sequence/der_encode_subject_public_key_info.o \
src/pk/asn1/der/sequence/der_decode_subject_public_key_info.o \
src/pk/asn1/der/sequence/der_decode_sequence_ex.o \
src/pk/asn1/der/sequence/der_decode_sequence_flexi.o \
src/pk/asn1/der/sequence/der_decode_sequence_multi.o \

View File

@ -7,6 +7,19 @@ enum {
int rand_prime(void *N, long len, prng_state *prng, int wprng);
enum {
PKA_RSA,
PKA_DSA
};
typedef struct Oid {
unsigned long OID[16];
/** Length of DER encoding */
unsigned long OIDlen;
} oid_st;
int pk_get_oid(int pk, oid_st *st);
/* ---- RSA ---- */
#ifdef LTC_MRSA
@ -429,7 +442,8 @@ enum {
LTC_ASN1_CHOICE,
LTC_ASN1_SEQUENCE,
LTC_ASN1_SET,
LTC_ASN1_SETOF
LTC_ASN1_SETOF,
LTC_ASN1_RAW_BIT_STRING,
};
/** A LTC ASN.1 list type */
@ -470,6 +484,15 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
unsigned long *outlen);
/* SUBJECT PUBLIC KEY INFO */
int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
unsigned int algorithm, void* public_key, unsigned long public_key_len,
unsigned long parameters_type, void* parameters, unsigned long parameters_len);
int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
unsigned int algorithm, void* public_key, unsigned long* public_key_len,
unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len);
/* SET */
#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0)
#define der_length_set der_length_sequence
@ -509,6 +532,10 @@ int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
int der_length_bit_string(unsigned long nbits, unsigned long *outlen);
/* OCTET STRING */

39
src/misc/pk_get_oid.c Normal file
View File

@ -0,0 +1,39 @@
/* LibTomCrypt, modular cryptographic library
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
*/
#include "tomcrypt.h"
static const oid_st rsa_oid = {
.OIDlen = 7,
.OID = { 1, 2, 840, 113549, 1, 1, 1 },
};
static const oid_st dsa_oid = {
.OIDlen = 6,
.OID = { 1, 2, 840, 10040, 4, 1 },
};
/*
Returns the OID of the public key algorithm.
@return CRYPT_OK if valid
*/
int pk_get_oid(int pk, oid_st *st)
{
switch (pk) {
case PKA_RSA:
memcpy(st, &rsa_oid, sizeof(*st));
break;
case PKA_DSA:
memcpy(st, &dsa_oid, sizeof(*st));
break;
default:
return CRYPT_INVALID_ARG;
}
return CRYPT_OK;
}

View File

@ -0,0 +1,106 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
/**
@file der_decode_bit_string.c
ASN.1 DER, encode a BIT STRING, Tom St Denis
*/
#ifdef LTC_DER
#define setbit(v, n) (v=((unsigned char)(v) | (1U << (unsigned char)(n))))
/**
Store a BIT STRING
@param in The DER encoded BIT STRING
@param inlen The size of the DER BIT STRING
@param out [out] The array of bits stored (8 per char)
@param outlen [in/out] The number of bits stored
@return CRYPT_OK if successful
*/
int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long dlen, blen, x, y;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
/* packet must be at least 4 bytes */
if (inlen < 4) {
return CRYPT_INVALID_ARG;
}
/* check for 0x03 */
if ((in[0]&0x1F) != 0x03) {
return CRYPT_INVALID_PACKET;
}
/* offset in the data */
x = 1;
/* get the length of the data */
if (in[x] & 0x80) {
/* long format get number of length bytes */
y = in[x++] & 0x7F;
/* invalid if 0 or > 2 */
if (y == 0 || y > 2) {
return CRYPT_INVALID_PACKET;
}
/* read the data len */
dlen = 0;
while (y--) {
dlen = (dlen << 8) | (unsigned long)in[x++];
}
} else {
/* short format */
dlen = in[x++] & 0x7F;
}
/* is the data len too long or too short? */
if ((dlen == 0) || (dlen + x > inlen)) {
return CRYPT_INVALID_PACKET;
}
/* get padding count */
blen = ((dlen - 1) << 3) - (in[x++] & 7);
/* too many bits? */
if (blen > *outlen) {
*outlen = blen;
return CRYPT_BUFFER_OVERFLOW;
}
/* decode/store the bits */
for (y = 0; y < blen; y++) {
if (in[x] & (1 << (7 - (y & 7)))) {
setbit(out[y/8], 7-(y%8));
}
if ((y & 7) == 7) {
++x;
}
}
/* we done */
*outlen = blen;
return CRYPT_OK;
}
#endif
/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_decode_bit_string.c,v $ */
/* $Revision: 1.5 $ */
/* $Date: 2006/12/28 01:27:24 $ */

View File

@ -0,0 +1,92 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@gmail.com, http://libtom.org
*/
#include "tomcrypt.h"
/**
@file der_encode_bit_string.c
ASN.1 DER, encode a BIT STRING, Tom St Denis
*/
#ifdef LTC_DER
#define getbit(n, k) (((n) & ( 1 << (k) )) >> (k))
/**
Store a BIT STRING
@param in The array of bits to store (8 per char)
@param inlen The number of bits tostore
@param out [out] The destination for the DER encoded BIT STRING
@param outlen [in/out] The max size and resulting size of the DER BIT STRING
@return CRYPT_OK if successful
*/
int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long len, x, y;
unsigned char buf;
int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
/* avoid overflows */
if ((err = der_length_bit_string(inlen, &len)) != CRYPT_OK) {
return err;
}
if (len > *outlen) {
*outlen = len;
return CRYPT_BUFFER_OVERFLOW;
}
/* store header (include bit padding count in length) */
x = 0;
y = (inlen >> 3) + ((inlen&7) ? 1 : 0) + 1;
out[x++] = 0x03;
if (y < 128) {
out[x++] = (unsigned char)y;
} else if (y < 256) {
out[x++] = 0x81;
out[x++] = (unsigned char)y;
} else if (y < 65536) {
out[x++] = 0x82;
out[x++] = (unsigned char)((y>>8)&255);
out[x++] = (unsigned char)(y&255);
}
/* store number of zero padding bits */
out[x++] = (unsigned char)((8 - inlen) & 7);
/* store the bits in big endian format */
for (y = buf = 0; y < inlen; y++) {
buf |= (getbit(in[y/8],7-y%8)?1:0) << (7 - (y & 7));
if ((y & 7) == 7) {
out[x++] = buf;
buf = 0;
}
}
/* store last byte */
if (inlen & 7) {
out[x++] = buf;
}
*outlen = x;
return CRYPT_OK;
}
#endif
/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/bit/der_encode_bit_string.c,v $ */
/* $Revision: 1.5 $ */
/* $Date: 2006/12/28 01:27:24 $ */

View File

@ -139,6 +139,18 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
}
break;
case LTC_ASN1_RAW_BIT_STRING:
z = inlen;
if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
if (!ordered) { continue; }
goto LBL_ERR;
}
list[i].size = size;
if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_OCTET_STRING:
z = inlen;
if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {

View File

@ -0,0 +1,95 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
*/
#include "tomcrypt.h"
/**
@file der_encode_sequence_multi.c
ASN.1 DER, encode a Subject Public Key structure --nmav
*/
#ifdef LTC_DER
/* AlgorithmIdentifier := SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm
* }
*
* SubjectPublicKeyInfo := SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING
* }
*/
/**
Encode a SEQUENCE type using a VA list
@param out [out] Destination for data
@param outlen [in/out] Length of buffer and resulting length of output
@remark <...> is of the form <type, size, data> (int, unsigned long, void*)
@return CRYPT_OK on success
*/
int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
unsigned int algorithm, void* public_key, unsigned long* public_key_len,
unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len)
{
int err, len;
oid_st oid;
unsigned char *tmpbuf;
unsigned long tmpoid[16];
ltc_asn1_list alg_id[2];
ltc_asn1_list subject_pubkey[2];
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != 0);
err = pk_get_oid(algorithm, &oid);
if (err != CRYPT_OK) {
return err;
}
/* see if the OpenSSL DER format RSA public key will work */
tmpbuf = XCALLOC(1, MAX_RSA_SIZE*8);
if (tmpbuf == NULL) {
err = CRYPT_MEM;
goto LBL_ERR;
}
/* this includes the internal hash ID and optional params (NULL in this case) */
LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len);
/* the actual format of the SSL DER key is odd, it stores a RSAPublicKey in a **BIT** string ... so we have to extract it
then proceed to convert bit to octet
*/
LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, 2);
LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_RAW_BIT_STRING, tmpbuf, MAX_RSA_SIZE*8);
err=der_decode_sequence(in, inlen, subject_pubkey, 2UL);
if (err != CRYPT_OK) {
goto LBL_ERR;
}
len = subject_pubkey[1].size/8;
if (*public_key_len > len) {
memcpy(public_key, subject_pubkey[1].data, len);
*public_key_len = len;
} else {
*public_key_len = len;
err = CRYPT_BUFFER_OVERFLOW;
goto LBL_ERR;
}
err = CRYPT_OK;
LBL_ERR:
XFREE(tmpbuf);
return err;
}
#endif

View File

@ -73,6 +73,7 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
break;
case LTC_ASN1_BIT_STRING:
case LTC_ASN1_RAW_BIT_STRING:
if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
@ -233,6 +234,15 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
*outlen -= z;
break;
case LTC_ASN1_RAW_BIT_STRING:
z = *outlen;
if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
x += z;
*outlen -= z;
break;
case LTC_ASN1_OCTET_STRING:
z = *outlen;
if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {

View File

@ -0,0 +1,69 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
*/
#include "tomcrypt.h"
/**
@file der_encode_sequence_multi.c
ASN.1 DER, encode a Subject Public Key structure --nmav
*/
#ifdef LTC_DER
/* AlgorithmIdentifier := SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm
* }
*
* SubjectPublicKeyInfo := SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING
* }
*/
/**
Encode a SEQUENCE type using a VA list
@param out [out] Destination for data
@param outlen [in/out] Length of buffer and resulting length of output
@remark <...> is of the form <type, size, data> (int, unsigned long, void*)
@return CRYPT_OK on success
*/
int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
unsigned int algorithm, void* public_key, unsigned long public_key_len,
unsigned long parameters_type, void* parameters, unsigned long parameters_len)
{
int err;
ltc_asn1_list alg_id[2];
oid_st oid;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
err = pk_get_oid(algorithm, &oid);
if (err != CRYPT_OK) {
return err;
}
alg_id[0].data = oid.OID;
alg_id[0].size = oid.OIDlen;
alg_id[0].type = LTC_ASN1_OBJECT_IDENTIFIER;
alg_id[1].data = parameters;
alg_id[1].size = parameters_len;
alg_id[1].type = parameters_type;
return der_encode_sequence_multi(out, outlen,
LTC_ASN1_SEQUENCE, (unsigned long)sizeof(alg_id)/sizeof(alg_id[0]), alg_id,
LTC_ASN1_RAW_BIT_STRING, (unsigned long)(public_key_len*8), public_key,
LTC_ASN1_EOL, 0UL, NULL);
}
#endif

View File

@ -29,6 +29,7 @@ int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key
{
unsigned char flags[1];
unsigned long zero=0;
int err;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
@ -43,8 +44,6 @@ int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key
return CRYPT_INVALID_ARG;
}
flags[0] = (type != PK_PUBLIC) ? 1 : 0;
/* This encoding is different from the one in original
* libtomcrypt. It uses a compatible encoding with gnutls
* and openssl
@ -60,13 +59,36 @@ int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key
LTC_ASN1_INTEGER, 1UL, key->x,
LTC_ASN1_EOL, 0UL, NULL);
} else {
return der_encode_sequence_multi(out, outlen,
LTC_ASN1_BIT_STRING, 1UL, flags,
LTC_ASN1_INTEGER, 1UL, key->g,
LTC_ASN1_INTEGER, 1UL, key->p,
LTC_ASN1_INTEGER, 1UL, key->q,
LTC_ASN1_INTEGER, 1UL, key->y,
LTC_ASN1_EOL, 0UL, NULL);
unsigned long tmplen = (mp_count_bits(key->y)/8)+8;
unsigned char* tmp = XMALLOC(tmplen);
ltc_asn1_list int_list[3];
if (tmp == NULL) {
return CRYPT_MEM;
}
err = der_encode_integer(key->y, tmp, &tmplen);
if (err != CRYPT_OK) {
goto error;
}
int_list[0].data = key->p;
int_list[0].size = 1UL;
int_list[0].type = LTC_ASN1_INTEGER;
int_list[1].data = key->q;
int_list[1].size = 1UL;
int_list[1].type = LTC_ASN1_INTEGER;
int_list[2].data = key->g;
int_list[2].size = 1UL;
int_list[2].type = LTC_ASN1_INTEGER;
err = der_encode_subject_public_key_info(out, outlen,
PKA_DSA, tmp, tmplen,
LTC_ASN1_SEQUENCE, int_list, sizeof(int_list)/sizeof(int_list[0]));
error:
XFREE(tmp);
return err;
}
}

View File

@ -26,9 +26,9 @@
*/
int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
{
unsigned char flags[1];
int err;
unsigned long zero = 0;
unsigned char* tmpbuf = NULL;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(key != NULL);
@ -41,30 +41,41 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
/* get key type */
if ((err = der_decode_sequence_multi(in, inlen,
LTC_ASN1_BIT_STRING, 1UL, flags,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
/* private key */
if ((err = der_decode_sequence_multi(in, inlen,
LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
LTC_ASN1_INTEGER, 1UL, key->p,
LTC_ASN1_INTEGER, 1UL, key->q,
LTC_ASN1_INTEGER, 1UL, key->g,
LTC_ASN1_INTEGER, 1UL, key->y,
LTC_ASN1_INTEGER, 1UL, key->x,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
goto error;
}
LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) {
key->type = PK_PRIVATE;
} else { /* public */
if ((err = der_decode_sequence_multi(in, inlen,
LTC_ASN1_BIT_STRING, 1UL, flags,
LTC_ASN1_INTEGER, 1UL, key->g,
LTC_ASN1_INTEGER, 1UL, key->p,
LTC_ASN1_INTEGER, 1UL, key->q,
LTC_ASN1_INTEGER, 1UL, key->y,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
goto error;
ltc_asn1_list params[3];
unsigned long tmpbuf_len = MAX_RSA_SIZE*8;
LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL);
LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL);
LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL);
tmpbuf = XCALLOC(1, tmpbuf_len);
if (tmpbuf == NULL) {
err = CRYPT_MEM;
goto LBL_ERR;
}
err = der_decode_subject_public_key_info(in, inlen,
PKA_DSA, tmpbuf, &tmpbuf_len,
LTC_ASN1_SEQUENCE, params, 3);
if (err != CRYPT_OK) {
goto LBL_ERR;
}
if ((err=der_decode_integer(tmpbuf, tmpbuf_len, key->y)) != CRYPT_OK) {
goto LBL_ERR;
}
XFREE(tmpbuf);
key->type = PK_PUBLIC;
}
key->qord = mp_unsigned_bin_size(key->q);
@ -72,11 +83,12 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
if (key->qord >= LTC_MDSA_MAX_GROUP || key->qord <= 15 ||
(unsigned long)key->qord >= mp_unsigned_bin_size(key->p) || (mp_unsigned_bin_size(key->p) - key->qord) >= LTC_MDSA_DELTA) {
err = CRYPT_INVALID_PACKET;
goto error;
goto LBL_ERR;
}
return CRYPT_OK;
error:
LBL_ERR:
XFREE(tmpbuf);
mp_clear_multi(key->p, key->g, key->q, key->x, key->y, NULL);
return err;
}

View File

@ -28,6 +28,7 @@
int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key)
{
unsigned long zero=0;
int err;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(key != NULL);
@ -55,10 +56,29 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key
LTC_ASN1_EOL, 0UL, NULL);
} else {
/* public key */
return der_encode_sequence_multi(out, outlen,
LTC_ASN1_INTEGER, 1UL, key->N,
LTC_ASN1_INTEGER, 1UL, key->e,
unsigned long tmplen = (mp_count_bits(key->N)/8)*2+8;
unsigned char* tmp = XMALLOC(tmplen);
if (tmp == NULL) {
return CRYPT_MEM;
}
err = der_encode_sequence_multi(tmp, &tmplen,
LTC_ASN1_INTEGER, 1UL, key->N,
LTC_ASN1_INTEGER, 1UL, key->e,
LTC_ASN1_EOL, 0UL, NULL);
if (err != CRYPT_OK) {
goto error;
}
err = der_encode_subject_public_key_info(out, outlen,
PKA_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0);
error:
XFREE(tmp);
return err;
}
}

View File

@ -28,10 +28,8 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
{
int err;
void *zero;
unsigned char *tmpbuf;
unsigned long t, x, y, z, tmpoid[16];
ltc_asn1_list ssl_pubkey_hashoid[2];
ltc_asn1_list ssl_pubkey[2];
unsigned char *tmpbuf=NULL;
unsigned long tmpbuf_len;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(key != NULL);
@ -44,41 +42,24 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
}
/* see if the OpenSSL DER format RSA public key will work */
tmpbuf = XCALLOC(1, MAX_RSA_SIZE*8);
tmpbuf_len = MAX_RSA_SIZE * 8;
tmpbuf = XCALLOC(1, tmpbuf_len);
if (tmpbuf == NULL) {
err = CRYPT_MEM;
goto LBL_ERR;
}
/* this includes the internal hash ID and optional params (NULL in this case) */
LTC_SET_ASN1(ssl_pubkey_hashoid, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
LTC_SET_ASN1(ssl_pubkey_hashoid, 1, LTC_ASN1_NULL, NULL, 0);
err = der_decode_subject_public_key_info(in, inlen,
PKA_RSA, tmpbuf, &tmpbuf_len,
LTC_ASN1_NULL, NULL, 0);
/* the actual format of the SSL DER key is odd, it stores a RSAPublicKey in a **BIT** string ... so we have to extract it
then proceed to convert bit to octet
*/
LTC_SET_ASN1(ssl_pubkey, 0, LTC_ASN1_SEQUENCE, &ssl_pubkey_hashoid, 2);
LTC_SET_ASN1(ssl_pubkey, 1, LTC_ASN1_BIT_STRING, tmpbuf, MAX_RSA_SIZE*8);
if (der_decode_sequence(in, inlen,
ssl_pubkey, 2UL) == CRYPT_OK) {
/* ok now we have to reassemble the BIT STRING to an OCTET STRING. Thanks OpenSSL... */
for (t = y = z = x = 0; x < ssl_pubkey[1].size; x++) {
y = (y << 1) | tmpbuf[x];
if (++z == 8) {
tmpbuf[t++] = (unsigned char)y;
y = 0;
z = 0;
}
}
if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */
/* now it should be SEQUENCE { INTEGER, INTEGER } */
if ((err = der_decode_sequence_multi(tmpbuf, t,
LTC_ASN1_INTEGER, 1UL, key->N,
LTC_ASN1_INTEGER, 1UL, key->e,
if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len,
LTC_ASN1_INTEGER, 1UL, key->N,
LTC_ASN1_INTEGER, 1UL, key->e,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
XFREE(tmpbuf);
goto LBL_ERR;
}
XFREE(tmpbuf);
@ -131,6 +112,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
}
return CRYPT_OK;
LBL_ERR:
XFREE(tmpbuf);
mp_clear_multi(key->d, key->e, key->N, key->dQ, key->dP, key->qP, key->p, key->q, NULL);
return err;
}