Codebase list libcryptx-perl / 130f5fd0-605e-470e-aa7d-f606741f9542/upstream src / ltc / misc / pbes / pbes2.c
130f5fd0-605e-470e-aa7d-f606741f9542/upstream

Tree @130f5fd0-605e-470e-aa7d-f606741f9542/upstream (Download .tar.gz)

pbes2.c @130f5fd0-605e-470e-aa7d-f606741f9542/upstream

e4cfa89
 
c14794b
 
 
 
1644699
 
c14794b
 
 
 
 
 
1644699
c14794b
 
 
 
 
 
 
 
 
1644699
c14794b
 
 
 
 
 
 
 
 
 
 
 
 
1644699
 
 
 
 
 
 
c14794b
 
1644699
c14794b
 
1644699
 
 
c14794b
 
 
 
 
1644699
 
 
c14794b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
da808b4
c14794b
 
 
 
 
1644699
c14794b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
da808b4
c14794b
 
 
 
 
 
 
 
 
 
 
1644699
c14794b
 
 
 
 
 
 
da808b4
 
c14794b
da808b4
 
 
 
 
 
 
c14794b
 
 
 
 
 
 
1644699
c14794b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"

#ifdef LTC_PBES

static const char * const s_oid_pbes2 =  "1.2.840.113549.1.5.13";
static const char * const s_oid_pbkdf2 = "1.2.840.113549.1.5.12";

typedef struct {
   const char *oid;
   const char *id;
} oid_id_st;

static const oid_id_st s_hmac_oid_names[] = {
   { "1.2.840.113549.2.7",  "sha1" },
   { "1.2.840.113549.2.8",  "sha224" },
   { "1.2.840.113549.2.9",  "sha256" },
   { "1.2.840.113549.2.10", "sha384" },
   { "1.2.840.113549.2.11", "sha512" },
   { "1.2.840.113549.2.12", "sha512-224" },
   { "1.2.840.113549.2.13", "sha512-256" },
};

static const pbes_properties s_pbes2_default_types[] = {
   { pkcs_5_alg2, "sha1",   "des",   8, 0 },
   { pkcs_5_alg2, "sha1",   "rc2",   4, 0 },
   { pkcs_5_alg2, "sha1",   "3des", 24, 0 },
   { pkcs_5_alg2, "sha1",   "aes",  16, 0 },
   { pkcs_5_alg2, "sha1",   "aes",  24, 0 },
   { pkcs_5_alg2, "sha1",   "aes",  32, 0 },
};

typedef struct {
   const pbes_properties *data;
   const char* oid;
} oid_to_pbes;

static const oid_to_pbes s_pbes2_list[] = {
   { &s_pbes2_default_types[0], "1.3.14.3.2.7"            },  /* http://www.oid-info.com/get/1.3.14.3.2.7            desCBC */
   { &s_pbes2_default_types[1], "1.2.840.113549.3.2"      },  /* http://www.oid-info.com/get/1.2.840.113549.3.2      rc2CBC */
   { &s_pbes2_default_types[2], "1.2.840.113549.3.7"      },  /* http://www.oid-info.com/get/1.2.840.113549.3.7      des-EDE3-CBC */
   { &s_pbes2_default_types[3], "2.16.840.1.101.3.4.1.2"  },  /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.2  aes128-CBC */
   { &s_pbes2_default_types[4], "2.16.840.1.101.3.4.1.22" },  /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.22 aes192-CBC */
   { &s_pbes2_default_types[5], "2.16.840.1.101.3.4.1.42" },  /* http://www.oid-info.com/get/2.16.840.1.101.3.4.1.42 aes256-CBC */
};

static int s_pbes2_from_oid(const ltc_asn1_list *cipher_oid, const ltc_asn1_list *hmac_oid, pbes_properties *res)
{
   unsigned int i;
   for (i = 0; i < sizeof(s_pbes2_list)/sizeof(s_pbes2_list[0]); ++i) {
      if (pk_oid_cmp_with_asn1(s_pbes2_list[i].oid, cipher_oid) == CRYPT_OK) {
         *res = *s_pbes2_list[i].data;
         break;
      }
   }
   if (res->c == NULL) return CRYPT_INVALID_CIPHER;
   if (hmac_oid != NULL) {
      for (i = 0; i < sizeof(s_hmac_oid_names)/sizeof(s_hmac_oid_names[0]); ++i) {
         if (pk_oid_cmp_with_asn1(s_hmac_oid_names[i].oid, hmac_oid) == CRYPT_OK) {
            res->h = s_hmac_oid_names[i].id;
            return CRYPT_OK;
         }
      }
      return CRYPT_INVALID_HASH;
   }
   return CRYPT_OK;
}


/**
   Extract PBES2 parameters

   @param s     The start of the sequence with potential PBES2 parameters
   @param res   Pointer to where the extracted parameters should be stored
   @return CRYPT_OK on success
*/
int pbes2_extract(const ltc_asn1_list *s, pbes_arg *res)
{
   unsigned long klen;
   ltc_asn1_list *lkdf, *lenc, *loptseq, *liter, *lhmac;
   int err;

   LTC_ARGCHK(s   != NULL);
   LTC_ARGCHK(res != NULL);

   if ((err = pk_oid_cmp_with_asn1(s_oid_pbes2, s)) != CRYPT_OK) return err;

   if (!LTC_ASN1_IS_TYPE(s->next, LTC_ASN1_SEQUENCE) ||
       !LTC_ASN1_IS_TYPE(s->next->child, LTC_ASN1_SEQUENCE) ||
       !LTC_ASN1_IS_TYPE(s->next->child->child, LTC_ASN1_OBJECT_IDENTIFIER) ||
       !LTC_ASN1_IS_TYPE(s->next->child->child->next, LTC_ASN1_SEQUENCE) ||
       !LTC_ASN1_IS_TYPE(s->next->child->next, LTC_ASN1_SEQUENCE) ||
       !LTC_ASN1_IS_TYPE(s->next->child->next->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
      return CRYPT_INVALID_PACKET;
   }
   /* PBES2: encrypted pkcs8 - PBES2+PBKDF2+des-ede3-cbc:
    *  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             :PBES2 (== 1.2.840.113549.1.5.13) (== *s)
    * 17:d=2  hl=2 l=  65 cons:     SEQUENCE
    * 19:d=3  hl=2 l=  41 cons:       SEQUENCE
    * 21:d=4  hl=2 l=   9 prim:         OBJECT         :PBKDF2 (== *lkdf)
    * 32:d=4  hl=2 l=  28 cons:         SEQUENCE
    * 34:d=5  hl=2 l=   8 prim:           OCTET STRING [HEX DUMP]:28BA4ABF6AA76A3D (== res->salt)
    * 44:d=5  hl=2 l=   2 prim:           INTEGER      :0800 (== res->iterations, *liter)
    * 48:d=5  hl=2 l=  12 cons:           SEQUENCE     (== *loptseq   - this sequence is optional, may be missing)
    * 50:d=6  hl=2 l=   8 prim:             OBJECT     :hmacWithSHA256 (== *lhmac)
    * 60:d=6  hl=2 l=   0 prim:             NULL
    * 62:d=3  hl=2 l=  20 cons:       SEQUENCE
    * 64:d=4  hl=2 l=   8 prim:         OBJECT         :des-ede3-cbc (== *lenc)
    * 74:d=4  hl=2 l=   8 prim:         OCTET STRING   [HEX DUMP]:B1404C4688DC9A5A
    * 84:d=1  hl=4 l= 296 prim:   OCTET STRING         :bytes (== encrypted data)
    */
   lkdf = s->next->child->child;
   lenc = s->next->child->next->child;

   if ((err = pk_oid_cmp_with_asn1(s_oid_pbkdf2, lkdf)) != CRYPT_OK) return err;

   if (!LTC_ASN1_IS_TYPE(lkdf->next, LTC_ASN1_SEQUENCE) ||
       !LTC_ASN1_IS_TYPE(lkdf->next->child, LTC_ASN1_OCTET_STRING) ||
       !LTC_ASN1_IS_TYPE(lkdf->next->child->next, LTC_ASN1_INTEGER)) {
      return CRYPT_INVALID_PACKET;
   }

   liter = lkdf->next->child->next;
   loptseq = liter->next;
   res->salt = lkdf->next->child;
   res->iterations = mp_get_int(liter->data);

   /* There's an optional INTEGER keyLength after the iterations, skip that if it's there.
    * c.f. RFC 2898 A.2 PBKDF2 */
   if(LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_INTEGER)) {
      loptseq = loptseq->next;
   }

   /* this sequence is optional */
   lhmac = NULL;
   if (LTC_ASN1_IS_TYPE(loptseq, LTC_ASN1_SEQUENCE) &&
       LTC_ASN1_IS_TYPE(loptseq->child, LTC_ASN1_OBJECT_IDENTIFIER)) {
      lhmac = loptseq->child;
   }
   if ((err = s_pbes2_from_oid(lenc, lhmac, &res->type)) != CRYPT_OK) return err;

   if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_OCTET_STRING)) {
      /* 'NON-RC2'-CBC */
      res->iv = lenc->next;
   } else if (LTC_ASN1_IS_TYPE(lenc->next, LTC_ASN1_SEQUENCE)) {
      /* RC2-CBC is a bit special ...
       *
       * RC2-CBC-Parameter ::= SEQUENCE {
       *     rc2ParameterVersion INTEGER OPTIONAL,
       *     iv OCTET STRING (SIZE(8)) }
       */
      if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_INTEGER) &&
          LTC_ASN1_IS_TYPE(lenc->next->child->next, LTC_ASN1_OCTET_STRING)) {
         klen = mp_get_int(lenc->next->child->data);
         res->iv   = lenc->next->child->next;
         /*
          * Effective Key Bits         Encoding
          *         40                    160
          *         64                    120
          *        128                     58
          *       b >= 256                  b
          */
         switch (klen) {
            case 160:
               res->key_bits = 40;
               break;
            case 120:
               res->key_bits = 64;
               break;
            case 58:
               res->key_bits = 128;
               break;
            default:
               /* We don't handle undefined Key Bits */
               if (klen < 256) return CRYPT_INVALID_KEYSIZE;

               res->key_bits = klen;
               break;
         }
      } else if (LTC_ASN1_IS_TYPE(lenc->next->child, LTC_ASN1_OCTET_STRING)) {
         res->iv   = lenc->next->child;
         /*
          * If the rc2ParameterVersion field is omitted, the "effective key bits"
          * defaults to 32.
          */
         res->key_bits = 32;
      } else {
         return CRYPT_INVALID_PACKET;
      }
   }

   return CRYPT_OK;
}

#endif