Browse Source

add (private) `rsa_import_pkcs1()`

Signed-off-by: Steffen Jaeckel <[email protected]>
Steffen Jaeckel 3 years ago
parent
commit
4a1477e289
3 changed files with 78 additions and 66 deletions
  1. 1 0
      src/headers/tomcrypt_private.h
  2. 69 45
      src/pk/rsa/rsa_import.c
  3. 8 21
      src/pk/rsa/rsa_import_pkcs8.c

+ 1 - 0
src/headers/tomcrypt_private.h

@@ -236,6 +236,7 @@ int rsa_init(rsa_key *key);
 void rsa_shrink_key(rsa_key *key);
 void rsa_shrink_key(rsa_key *key);
 int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e,
 int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e,
                       rsa_key *key); /* used by op-tee */
                       rsa_key *key); /* used by op-tee */
+int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key);
 #endif /* LTC_MRSA */
 #endif /* LTC_MRSA */
 
 
 /* ---- DH Routines ---- */
 /* ---- DH Routines ---- */

+ 69 - 45
src/pk/rsa/rsa_import.c

@@ -9,8 +9,74 @@
 
 
 #ifdef LTC_MRSA
 #ifdef LTC_MRSA
 
 
+
+/**
+  Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only]
+
+    The `key` passed into this function has to be already initialized and will
+    NOT be free'd on error!
+
+  @param in      The packet to import from
+  @param inlen   It's length (octets)
+  @param key     [out] Destination for newly imported key
+  @return CRYPT_OK if successful
+*/
+int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key)
+{
+   int   err;
+   unsigned long version = -1;
+
+   err = der_decode_sequence_multi(in, inlen, LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+                                              LTC_ASN1_EOL,     0UL, NULL);
+
+   if (err == CRYPT_OVERFLOW) {
+      /* the version would fit into an LTC_ASN1_SHORT_INTEGER
+       * so we try to decode as a public key
+       */
+      if ((err = der_decode_sequence_multi(in, inlen,
+                                     LTC_ASN1_INTEGER, 1UL, key->N,
+                                     LTC_ASN1_INTEGER, 1UL, key->e,
+                                     LTC_ASN1_EOL,     0UL, NULL)) == CRYPT_OK) {
+         key->type = PK_PUBLIC;
+      }
+      goto LBL_OUT;
+   } else if (err != CRYPT_INPUT_TOO_LONG) {
+      /* couldn't decode the version, so error out */
+      goto LBL_OUT;
+   }
+
+   if (version == 0) {
+      /* it's a private key */
+      if ((err = der_decode_sequence_multi(in, inlen,
+                          LTC_ASN1_SHORT_INTEGER, 1UL, &version,
+                          LTC_ASN1_INTEGER, 1UL, key->N,
+                          LTC_ASN1_INTEGER, 1UL, key->e,
+                          LTC_ASN1_INTEGER, 1UL, key->d,
+                          LTC_ASN1_INTEGER, 1UL, key->p,
+                          LTC_ASN1_INTEGER, 1UL, key->q,
+                          LTC_ASN1_INTEGER, 1UL, key->dP,
+                          LTC_ASN1_INTEGER, 1UL, key->dQ,
+                          LTC_ASN1_INTEGER, 1UL, key->qP,
+                          LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
+         goto LBL_OUT;
+      }
+      key->type = PK_PRIVATE;
+   } else if (version == 1) {
+      /* we don't support multi-prime RSA */
+      err = CRYPT_PK_INVALID_TYPE;
+      goto LBL_OUT;
+   }
+   err = CRYPT_OK;
+LBL_OUT:
+   return err;
+}
+
 /**
 /**
-  Import an RSAPublicKey or RSAPrivateKey [two-prime only, only support >= 1024-bit keys, defined in PKCS #1 v2.1]
+  Import multiple formats of RSA public and private keys.
+
+     RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only]
+     SubjectPublicKeyInfo formatted public keys
+
   @param in      The packet to import from
   @param in      The packet to import from
   @param inlen   It's length (octets)
   @param inlen   It's length (octets)
   @param key     [out] Destination for newly imported key
   @param key     [out] Destination for newly imported key
@@ -19,7 +85,6 @@
 int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
 int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
 {
 {
    int           err;
    int           err;
-   void         *zero;
    unsigned char *tmpbuf=NULL;
    unsigned char *tmpbuf=NULL;
    unsigned long tmpbuf_len, len;
    unsigned long tmpbuf_len, len;
 
 
@@ -60,50 +125,9 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
    }
    }
 
 
    /* not SSL public key, try to match against PKCS #1 standards */
    /* not SSL public key, try to match against PKCS #1 standards */
-   err = der_decode_sequence_multi(in, inlen, LTC_ASN1_INTEGER, 1UL, key->N,
-                                              LTC_ASN1_EOL,     0UL, NULL);
-
-   if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
-      goto LBL_ERR;
-   }
-
-   if (mp_cmp_d(key->N, 0) == LTC_MP_EQ) {
-      if ((err = mp_init(&zero)) != CRYPT_OK) {
-         goto LBL_ERR;
-      }
-      /* it's a private key */
-      if ((err = der_decode_sequence_multi(in, inlen,
-                          LTC_ASN1_INTEGER, 1UL, zero,
-                          LTC_ASN1_INTEGER, 1UL, key->N,
-                          LTC_ASN1_INTEGER, 1UL, key->e,
-                          LTC_ASN1_INTEGER, 1UL, key->d,
-                          LTC_ASN1_INTEGER, 1UL, key->p,
-                          LTC_ASN1_INTEGER, 1UL, key->q,
-                          LTC_ASN1_INTEGER, 1UL, key->dP,
-                          LTC_ASN1_INTEGER, 1UL, key->dQ,
-                          LTC_ASN1_INTEGER, 1UL, key->qP,
-                          LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
-         mp_clear(zero);
-         goto LBL_ERR;
-      }
-      mp_clear(zero);
-      key->type = PK_PRIVATE;
-   } else if (mp_cmp_d(key->N, 1) == LTC_MP_EQ) {
-      /* we don't support multi-prime RSA */
-      err = CRYPT_PK_INVALID_TYPE;
-      goto LBL_ERR;
-   } else {
-      /* it's a public key and we lack e */
-      if ((err = der_decode_sequence_multi(in, inlen,
-                                     LTC_ASN1_INTEGER, 1UL, key->N,
-                                     LTC_ASN1_INTEGER, 1UL, key->e,
-                                     LTC_ASN1_EOL,     0UL, NULL)) != CRYPT_OK) {
-         goto LBL_ERR;
-      }
-      key->type = PK_PUBLIC;
+   if ((err = rsa_import_pkcs1(in, inlen, key)) == CRYPT_OK) {
+      goto LBL_FREE;
    }
    }
-   err = CRYPT_OK;
-   goto LBL_FREE;
 
 
 LBL_ERR:
 LBL_ERR:
    rsa_free(key);
    rsa_free(key);

+ 8 - 21
src/pk/rsa/rsa_import_pkcs8.c

@@ -46,10 +46,9 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
                      rsa_key *key)
                      rsa_key *key)
 {
 {
    int           err;
    int           err;
-   void          *zero, *iter;
    unsigned char *buf1 = NULL, *buf2 = NULL;
    unsigned char *buf1 = NULL, *buf2 = NULL;
    unsigned long buf1len, buf2len;
    unsigned long buf1len, buf2len;
-   unsigned long oid[16];
+   unsigned long oid[16], version;
    const char    *rsaoid;
    const char    *rsaoid;
    ltc_asn1_list alg_seq[2], top_seq[3];
    ltc_asn1_list alg_seq[2], top_seq[3];
    ltc_asn1_list *l = NULL;
    ltc_asn1_list *l = NULL;
@@ -72,9 +71,8 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
    buf2 = XMALLOC(buf2len);
    buf2 = XMALLOC(buf2len);
    if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; }
    if (buf2 == NULL) { err = CRYPT_MEM; goto LBL_FREE1; }
 
 
-   if ((err = mp_init_multi(&zero, &iter, NULL)) != CRYPT_OK) { goto LBL_FREE2; }
    /* init key */
    /* init key */
-   if ((err = rsa_init(key)) != CRYPT_OK) { goto LBL_FREE3; }
+   if ((err = rsa_init(key)) != CRYPT_OK) { goto LBL_FREE2; }
 
 
    /* try to decode encrypted priv key */
    /* try to decode encrypted priv key */
    if ((err = pkcs8_decode_flexi(in, inlen, passwd, passwdlen, &l)) != CRYPT_OK) {
    if ((err = pkcs8_decode_flexi(in, inlen, passwd, passwdlen, &l)) != CRYPT_OK) {
@@ -86,7 +84,7 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
    /* try to decode unencrypted priv key */
    /* try to decode unencrypted priv key */
    LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
    LTC_SET_ASN1(alg_seq, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, 16UL);
    LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL);
    LTC_SET_ASN1(alg_seq, 1, LTC_ASN1_NULL, NULL, 0UL);
-   LTC_SET_ASN1(top_seq, 0, LTC_ASN1_INTEGER, zero, 1UL);
+   LTC_SET_ASN1(top_seq, 0, LTC_ASN1_SHORT_INTEGER, &version, 1UL);
    LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL);
    LTC_SET_ASN1(top_seq, 1, LTC_ASN1_SEQUENCE, alg_seq, 2UL);
    LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len);
    LTC_SET_ASN1(top_seq, 2, LTC_ASN1_OCTET_STRING, buf1, buf1len);
    err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL);
    err=der_decode_sequence(decrypted, decryptedlen, top_seq, 3UL);
@@ -97,28 +95,17 @@ int rsa_import_pkcs8(const unsigned char *in, unsigned long inlen,
       goto LBL_ERR;
       goto LBL_ERR;
    }
    }
 
 
-   err = der_decode_sequence_multi(buf1, top_seq[2].size,
-                                   LTC_ASN1_INTEGER, 1UL, zero,
-                                   LTC_ASN1_INTEGER, 1UL, key->N,
-                                   LTC_ASN1_INTEGER, 1UL, key->e,
-                                   LTC_ASN1_INTEGER, 1UL, key->d,
-                                   LTC_ASN1_INTEGER, 1UL, key->p,
-                                   LTC_ASN1_INTEGER, 1UL, key->q,
-                                   LTC_ASN1_INTEGER, 1UL, key->dP,
-                                   LTC_ASN1_INTEGER, 1UL, key->dQ,
-                                   LTC_ASN1_INTEGER, 1UL, key->qP,
-                                   LTC_ASN1_EOL,     0UL, NULL);
-   if (err != CRYPT_OK) { goto LBL_ERR; }
+   if ((err = rsa_import_pkcs1(buf1, top_seq[2].size, key)) != CRYPT_OK) {
+      goto LBL_ERR;
+   }
    key->type = PK_PRIVATE;
    key->type = PK_PRIVATE;
    err = CRYPT_OK;
    err = CRYPT_OK;
-   goto LBL_FREE3;
+   goto LBL_FREE2;
 
 
 LBL_ERR:
 LBL_ERR:
    rsa_free(key);
    rsa_free(key);
-LBL_FREE3:
-   mp_clear_multi(iter, zero, NULL);
-   if (l) der_free_sequence_flexi(l);
 LBL_FREE2:
 LBL_FREE2:
+   if (l) der_free_sequence_flexi(l);
    XFREE(buf2);
    XFREE(buf2);
 LBL_FREE1:
 LBL_FREE1:
    XFREE(buf1);
    XFREE(buf1);