Browse Source

implement pkcs8_decode_flexi()

Steffen Jaeckel 7 years ago
parent
commit
bc673c2853

+ 5 - 0
src/headers/tomcrypt_custom.h

@@ -567,6 +567,11 @@
    #define LTC_PKCS_8
 #endif
 
+#ifdef LTC_PKCS_8
+   #define LTC_PADDING
+   #define LTC_PBES
+#endif
+
 #if defined(LTC_PELICAN) && !defined(LTC_RIJNDAEL)
    #error Pelican-MAC requires LTC_RIJNDAEL
 #endif

+ 9 - 0
src/headers/tomcrypt_private.h

@@ -342,6 +342,15 @@ int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2);
 
 /* tomcrypt_pkcs.h */
 
+#ifdef LTC_PKCS_8
+
+int pkcs8_decode_flexi(const unsigned char  *in,  unsigned long inlen,
+                                    const void  *pwd, unsigned long pwdlen,
+                                 ltc_asn1_list **decoded_list);
+
+#endif  /* LTC_PKCS_8 */
+
+
 #ifdef LTC_PKCS_12
 
 int pkcs12_utf8_to_utf16(const unsigned char *in,  unsigned long  inlen,

+ 90 - 0
src/pk/asn1/pkcs8/pkcs8_decode_flexi.c

@@ -10,6 +10,96 @@
 
 #ifdef LTC_PKCS_8
 
+/**
+   PKCS#8 decrypt if necessary & flexi-decode
+
+   @param in            Pointer to the ASN.1 encoded input data
+   @param inlen         Length of the input data
+   @param pwd           Pointer to the password that was used when encrypting
+   @param pwdlen        Length of the password
+   @param decoded_list  Pointer to a pointer for the flexi-decoded list
+   @return CRYPT_OK on success
+*/
+int pkcs8_decode_flexi(const unsigned char  *in,  unsigned long inlen,
+                                const void  *pwd, unsigned long pwdlen,
+                             ltc_asn1_list **decoded_list)
+{
+   unsigned long len = inlen;
+   unsigned long dec_size;
+   unsigned char *dec_data = NULL;
+   ltc_asn1_list *l = NULL;
+   int err;
+
+   LTC_ARGCHK(in           != NULL);
+   LTC_ARGCHK(decoded_list != NULL);
+
+   *decoded_list = NULL;
+   if ((err = der_decode_sequence_flexi(in, &len, &l)) == CRYPT_OK) {
+      /* the following "if" detects whether it is encrypted or not */
+      /* PKCS8 Setup
+       *  0:d=0  hl=4 l= 380 cons: SEQUENCE
+       *  4:d=1  hl=2 l=  78 cons:   SEQUENCE
+       *  6:d=2  hl=2 l=   9 prim:     OBJECT             :OID indicating PBES1 or PBES2 (== *lalgoid)
+       * 17:d=2  hl=2 l=  65 cons:     SEQUENCE
+       *     Stuff in between is dependent on whether it's PBES1 or PBES2
+       * 84:d=1  hl=4 l= 296 prim:   OCTET STRING         :bytes (== encrypted data)
+       */
+      if (l->type == LTC_ASN1_SEQUENCE &&
+          LTC_ASN1_IS_TYPE(l->child, LTC_ASN1_SEQUENCE) &&
+          LTC_ASN1_IS_TYPE(l->child->child, LTC_ASN1_OBJECT_IDENTIFIER) &&
+          LTC_ASN1_IS_TYPE(l->child->child->next, LTC_ASN1_SEQUENCE) &&
+          LTC_ASN1_IS_TYPE(l->child->next, LTC_ASN1_OCTET_STRING)) {
+         ltc_asn1_list *lalgoid = l->child->child;
+         pbes_arg pbes;
+
+         XMEMSET(&pbes, 0, sizeof(pbes));
+
+         if (pbes1_extract(lalgoid, &pbes) == CRYPT_OK) {
+            /* Successfully extracted PBES1 parameters */
+         } else if (pbes2_extract(lalgoid, &pbes) == CRYPT_OK) {
+            /* Successfully extracted PBES2 parameters */
+         } else {
+            /* unsupported encryption */
+            err = CRYPT_INVALID_PACKET;
+            goto LBL_DONE;
+         }
+
+         pbes.enc_data = l->child->next;
+         pbes.pwd = pwd;
+         pbes.pwdlen = pwdlen;
+
+         dec_size = pbes.enc_data->size;
+         if ((dec_data = XMALLOC(dec_size)) == NULL) {
+            err = CRYPT_MEM;
+            goto LBL_DONE;
+         }
+
+         if ((err = pbes_decrypt(&pbes, dec_data, &dec_size)) != CRYPT_OK) goto LBL_DONE;
+
+         der_free_sequence_flexi(l);
+         l = NULL;
+         err = der_decode_sequence_flexi(dec_data, &dec_size, &l);
+         if (err != CRYPT_OK) goto LBL_DONE;
+         *decoded_list = l;
+      }
+      else {
+         /* not encrypted */
+         err = CRYPT_OK;
+         *decoded_list = l;
+      }
+      /* Set l to NULL so it won't be free'd */
+      l = NULL;
+   }
+
+LBL_DONE:
+   if (l) der_free_sequence_flexi(l);
+   if (dec_data) {
+      zeromem(dec_data, dec_size);
+      XFREE(dec_data);
+   }
+   return err;
+}
+
 #endif
 
 /* ref:         $Format:%D$ */