浏览代码

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

Nikos Mavrogiannopoulos 14 年之前
父节点
当前提交
fa22e791d4

+ 4 - 0
makefile

@@ -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 \

+ 28 - 1
src/headers/tomcrypt_pk.h

@@ -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 - 0
src/misc/pk_get_oid.c

@@ -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;
+}

+ 106 - 0
src/pk/asn1/der/bit/der_decode_raw_bit_string.c

@@ -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, [email protected], 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 $ */

+ 92 - 0
src/pk/asn1/der/bit/der_encode_raw_bit_string.c

@@ -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, [email protected], 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 $ */

+ 12 - 0
src/pk/asn1/der/sequence/der_decode_sequence_ex.c

@@ -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) {

+ 95 - 0
src/pk/asn1/der/sequence/der_decode_subject_public_key_info.c

@@ -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

+ 10 - 0
src/pk/asn1/der/sequence/der_encode_sequence_ex.c

@@ -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) {

+ 69 - 0
src/pk/asn1/der/sequence/der_encode_subject_public_key_info.c

@@ -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
+
+

+ 31 - 9
src/pk/dsa/dsa_export.c

@@ -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;
    }
 }
 

+ 30 - 18
src/pk/dsa/dsa_import.c

@@ -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;
 }

+ 23 - 3
src/pk/rsa/rsa_export.c

@@ -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;
+
    }
 }
 

+ 12 - 30
src/pk/rsa/rsa_import.c

@@ -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;
 }