Bug 1268141 - pk12util can't import PKCS#12 files encrypted with AES-128-CBC, r=rrelyea
authorDaiki Ueno <dueno@redhat.com>
Mon, 30 Jan 2017 10:33:55 +0100
changeset 13167 09d1a0757431fa52ae025138da654c698141971b
parent 13166 806c3106536feea0827ec54729a52b5cbac8a496
child 13168 ef508cdcb5803a842fab19c406fb19db75befd35
push id2045
push userkaie@kuix.de
push dateThu, 23 Feb 2017 12:28:28 +0000
reviewersrrelyea
bugs1268141
Bug 1268141 - pk12util can't import PKCS#12 files encrypted with AES-128-CBC, r=rrelyea
cmd/pk12util/pk12util.c
lib/pk11wrap/pk11pbe.c
lib/pkcs12/p12d.c
lib/pkcs12/p12e.c
lib/pkcs12/p12local.c
lib/pkcs12/p12local.h
lib/pkcs12/p12plcy.c
lib/pkcs7/p7create.c
lib/pkcs7/secpkcs7.h
lib/util/ciferfam.h
tests/tools/tools.sh
--- a/cmd/pk12util/pk12util.c
+++ b/cmd/pk12util/pk12util.c
@@ -856,16 +856,19 @@ static void
 p12u_EnableAllCiphers()
 {
     SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
     SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1);
     SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1);
     SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1);
     SEC_PKCS12EnableCipher(PKCS12_DES_56, 1);
     SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1);
+    SEC_PKCS12EnableCipher(PKCS12_AES_CBC_128, 1);
+    SEC_PKCS12EnableCipher(PKCS12_AES_CBC_192, 1);
+    SEC_PKCS12EnableCipher(PKCS12_AES_CBC_256, 1);
     SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1);
 }
 
 static PRUintn
 P12U_Init(char *dir, char *dbprefix, PRBool listonly)
 {
     SECStatus rv;
     PK11_SetPasswordFunc(SECU_GetModulePassword);
--- a/lib/pk11wrap/pk11pbe.c
+++ b/lib/pk11wrap/pk11pbe.c
@@ -1,14 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "plarena.h"
 
+#include "blapit.h"
 #include "seccomon.h"
 #include "secitem.h"
 #include "secport.h"
 #include "hasht.h"
 #include "pkcs11t.h"
 #include "sechash.h"
 #include "secasn1.h"
 #include "secder.h"
@@ -296,27 +297,59 @@ SEC_PKCS5GetPBEAlgorithm(SECOidTag algTa
             break;
         default:
             return sec_pkcs5v2_get_pbe(algTag);
     }
 
     return SEC_OID_UNKNOWN;
 }
 
+static PRBool
+sec_pkcs5_is_algorithm_v2_aes_algorithm(SECOidTag algorithm)
+{
+    switch (algorithm) {
+        case SEC_OID_AES_128_CBC:
+        case SEC_OID_AES_192_CBC:
+        case SEC_OID_AES_256_CBC:
+            return PR_TRUE;
+        default:
+            return PR_FALSE;
+    }
+}
+
+static int
+sec_pkcs5v2_aes_key_length(SECOidTag algorithm)
+{
+    switch (algorithm) {
+        /* The key length for the AES-CBC-Pad algorithms are
+         * determined from the undelying cipher algorithm.  */
+        case SEC_OID_AES_128_CBC:
+            return AES_128_KEY_LENGTH;
+        case SEC_OID_AES_192_CBC:
+            return AES_192_KEY_LENGTH;
+        case SEC_OID_AES_256_CBC:
+            return AES_256_KEY_LENGTH;
+        default:
+            break;
+    }
+    return 0;
+}
+
 /*
  * get the key length in bytes from a PKCS5 PBE
  */
-int
-sec_pkcs5v2_key_length(SECAlgorithmID *algid)
+static int
+sec_pkcs5v2_key_length(SECAlgorithmID *algid, SECAlgorithmID *cipherAlgId)
 {
     SECOidTag algorithm;
     PLArenaPool *arena = NULL;
     SEC_PKCS5PBEParameter p5_param;
     SECStatus rv;
     int length = -1;
+    SECOidTag cipherAlg = SEC_OID_UNKNOWN;
 
     algorithm = SECOID_GetAlgorithmTag(algid);
     /* sanity check, they should all be PBKDF2 here */
     if (algorithm != SEC_OID_PKCS5_PBKDF2) {
         return -1;
     }
 
     arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
@@ -325,17 +358,22 @@ sec_pkcs5v2_key_length(SECAlgorithmID *a
     }
     PORT_Memset(&p5_param, 0, sizeof(p5_param));
     rv = SEC_ASN1DecodeItem(arena, &p5_param,
                             SEC_PKCS5V2PBEParameterTemplate, &algid->parameters);
     if (rv != SECSuccess) {
         goto loser;
     }
 
-    if (p5_param.keyLength.data != NULL) {
+    if (cipherAlgId)
+        cipherAlg = SECOID_GetAlgorithmTag(cipherAlgId);
+
+    if (sec_pkcs5_is_algorithm_v2_aes_algorithm(cipherAlg)) {
+        length = sec_pkcs5v2_aes_key_length(cipherAlg);
+    } else if (p5_param.keyLength.data != NULL) {
         length = DER_GetInteger(&p5_param.keyLength);
     }
 
 loser:
     if (arena) {
         PORT_FreeArena(arena, PR_FALSE);
     }
     return length;
@@ -370,24 +408,25 @@ SEC_PKCS5GetKeyLength(SECAlgorithmID *al
         case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
             return 5;
         case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
         case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
         case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
         case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
             return 16;
         case SEC_OID_PKCS5_PBKDF2:
-            return sec_pkcs5v2_key_length(algid);
+            return sec_pkcs5v2_key_length(algid, NULL);
         case SEC_OID_PKCS5_PBES2:
         case SEC_OID_PKCS5_PBMAC1: {
             sec_pkcs5V2Parameter *pbeV2_param;
             int length = -1;
             pbeV2_param = sec_pkcs5_v2_get_v2_param(NULL, algid);
             if (pbeV2_param != NULL) {
-                length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId);
+                length = sec_pkcs5v2_key_length(&pbeV2_param->pbeAlgId,
+                                                &pbeV2_param->cipherAlgId);
                 sec_pkcs5_v2_destroy_v2_param(pbeV2_param);
             }
             return length;
         }
 
         default:
             break;
     }
@@ -609,16 +648,18 @@ sec_pkcs5CreateAlgorithmID(SECOidTag alg
             algorithm = sec_pkcs5v2_get_pbe(cipherAlgorithm);
         }
 
         /* set the PKCS5v2 specific parameters */
         if (keyLength == 0) {
             SECOidTag hashAlg = HASH_GetHashOidTagByHMACOidTag(cipherAlgorithm);
             if (hashAlg != SEC_OID_UNKNOWN) {
                 keyLength = HASH_ResultLenByOidTag(hashAlg);
+            } else if (sec_pkcs5_is_algorithm_v2_aes_algorithm(cipherAlgorithm)) {
+                keyLength = sec_pkcs5v2_aes_key_length(cipherAlgorithm);
             } else {
                 CK_MECHANISM_TYPE cryptoMech;
                 cryptoMech = PK11_AlgtagToMechanism(cipherAlgorithm);
                 if (cryptoMech == CKM_INVALID_MECHANISM) {
                     goto loser;
                 }
                 keyLength = PK11_GetMaxKeyLength(cryptoMech);
             }
--- a/lib/pkcs12/p12d.c
+++ b/lib/pkcs12/p12d.c
@@ -172,47 +172,71 @@ sec_pkcs12_proper_version(sec_PKCS12PFXI
 
 /* retrieve the key for decrypting the safe contents */
 static PK11SymKey *
 sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid)
 {
     SEC_PKCS12DecoderContext *p12dcx = (SEC_PKCS12DecoderContext *)arg;
     PK11SlotInfo *slot;
     PK11SymKey *bulkKey;
+    SECItem *pwitem;
+    SECItem decodedPwitem = { 0 };
+    SECOidTag algorithm;
 
     if (!p12dcx) {
         return NULL;
     }
 
     /* if no slot specified, use the internal key slot */
     if (p12dcx->slot) {
         slot = PK11_ReferenceSlot(p12dcx->slot);
     } else {
         slot = PK11_GetInternalKeySlot();
     }
 
-    bulkKey = PK11_PBEKeyGen(slot, algid, p12dcx->pwitem,
+    algorithm = SECOID_GetAlgorithmTag(algid);
+    pwitem = p12dcx->pwitem;
+
+    /* here we assume that the password is already encoded into
+     * BMPString by the caller.  if the encryption scheme is not the
+     * one defined in PKCS #12, decode the password back into
+     * UTF-8. */
+    if (!sec_pkcs12_is_pkcs12_pbe_algorithm(algorithm)) {
+        if (!sec_pkcs12_convert_item_to_unicode(NULL, &decodedPwitem,
+                                                p12dcx->pwitem,
+                                                PR_TRUE, PR_FALSE, PR_FALSE)) {
+            PORT_SetError(SEC_ERROR_NO_MEMORY);
+            return NULL;
+        }
+        pwitem = &decodedPwitem;
+    }
+
+    bulkKey = PK11_PBEKeyGen(slot, algid, pwitem,
                              PR_FALSE, p12dcx->wincx);
     /* some tokens can't generate PBE keys on their own, generate the
      * key in the internal slot, and let the Import code deal with it,
      * (if the slot can't generate PBEs, then we need to use the internal
      * slot anyway to unwrap). */
     if (!bulkKey && !PK11_IsInternal(slot)) {
         PK11_FreeSlot(slot);
         slot = PK11_GetInternalKeySlot();
-        bulkKey = PK11_PBEKeyGen(slot, algid, p12dcx->pwitem,
+        bulkKey = PK11_PBEKeyGen(slot, algid, pwitem,
                                  PR_FALSE, p12dcx->wincx);
     }
     PK11_FreeSlot(slot);
 
     /* set the password data on the key */
     if (bulkKey) {
         PK11_SetSymKeyUserData(bulkKey, p12dcx->pwitem, NULL);
     }
 
+    if (decodedPwitem.data) {
+        SECITEM_ZfreeItem(&decodedPwitem, PR_FALSE);
+    }
+
     return bulkKey;
 }
 
 /* XXX this needs to be modified to handle enveloped data.  most
  * likely, it should mirror the routines for SMIME in that regard.
  */
 static PRBool
 sec_pkcs12_decoder_decryption_allowed(SECAlgorithmID *algid,
--- a/lib/pkcs12/p12e.c
+++ b/lib/pkcs12/p12e.c
@@ -5,16 +5,17 @@
 #include "p12t.h"
 #include "p12.h"
 #include "plarena.h"
 #include "secitem.h"
 #include "secoid.h"
 #include "seccomon.h"
 #include "secport.h"
 #include "cert.h"
+#include "secpkcs5.h"
 #include "secpkcs7.h"
 #include "secasn1.h"
 #include "secerr.h"
 #include "pk11func.h"
 #include "p12plcy.h"
 #include "p12local.h"
 #include "prcpucfg.h"
 
@@ -373,29 +374,46 @@ SEC_PKCS12CreatePasswordPrivSafe(SEC_PKC
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         PORT_ArenaRelease(p12ctxt->arena, mark);
         return NULL;
     }
 
     safeInfo->itemCount = 0;
 
     /* create the encrypted safe */
-    safeInfo->cinfo = SEC_PKCS7CreateEncryptedData(privAlg, 0, p12ctxt->pwfn,
-                                                   p12ctxt->pwfnarg);
+    if (!SEC_PKCS5IsAlgorithmPBEAlgTag(privAlg) &&
+        PK11_AlgtagToMechanism(privAlg) == CKM_AES_CBC) {
+        safeInfo->cinfo = SEC_PKCS7CreateEncryptedDataWithPBEV2(SEC_OID_PKCS5_PBES2,
+                                                                privAlg,
+                                                                SEC_OID_UNKNOWN,
+                                                                0,
+                                                                p12ctxt->pwfn,
+                                                                p12ctxt->pwfnarg);
+    } else {
+        safeInfo->cinfo = SEC_PKCS7CreateEncryptedData(privAlg, 0, p12ctxt->pwfn,
+                                                       p12ctxt->pwfnarg);
+    }
     if (!safeInfo->cinfo) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         goto loser;
     }
     safeInfo->arena = p12ctxt->arena;
 
-    /* convert the password to unicode */
-    if (!sec_pkcs12_convert_item_to_unicode(NULL, &uniPwitem, pwitem,
-                                            PR_TRUE, PR_TRUE, PR_TRUE)) {
-        PORT_SetError(SEC_ERROR_NO_MEMORY);
-        goto loser;
+    if (sec_pkcs12_is_pkcs12_pbe_algorithm(privAlg)) {
+        /* convert the password to unicode */
+        if (!sec_pkcs12_convert_item_to_unicode(NULL, &uniPwitem, pwitem,
+                                                PR_TRUE, PR_TRUE, PR_TRUE)) {
+            PORT_SetError(SEC_ERROR_NO_MEMORY);
+            goto loser;
+        }
+    } else {
+        if (SECITEM_CopyItem(NULL, &uniPwitem, pwitem) != SECSuccess) {
+            PORT_SetError(SEC_ERROR_NO_MEMORY);
+            goto loser;
+        }
     }
     if (SECITEM_CopyItem(p12ctxt->arena, &safeInfo->pwitem, &uniPwitem) != SECSuccess) {
         PORT_SetError(SEC_ERROR_NO_MEMORY);
         goto loser;
     }
 
     /* generate the encryption key */
     slot = PK11_ReferenceSlot(p12ctxt->slot);
--- a/lib/pkcs12/p12local.c
+++ b/lib/pkcs12/p12local.c
@@ -944,16 +944,43 @@ sec_pkcs12_convert_item_to_unicode(PLAre
         }
         dest->len += 2;
         dest->data[dest->len - 1] = dest->data[dest->len - 2] = 0;
     }
 
     return PR_TRUE;
 }
 
+PRBool
+sec_pkcs12_is_pkcs12_pbe_algorithm(SECOidTag algorithm)
+{
+    switch (algorithm) {
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC:
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC:
+        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC:
+        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
+        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC:
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC:
+        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4:
+        case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4:
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4:
+        case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4:
+        /* those are actually PKCS #5 v1.5 PBEs, but we
+         * historically treat them in the same way as PKCS #12
+         * PBEs */
+        case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC:
+        case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC:
+        case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC:
+            return PR_TRUE;
+        default:
+            return PR_FALSE;
+    }
+}
+
 /* pkcs 12 templates */
 static const SEC_ASN1TemplateChooserPtr sec_pkcs12_shroud_chooser =
     sec_pkcs12_choose_shroud_type;
 
 const SEC_ASN1Template SEC_PKCS12CodedSafeBagTemplate[] =
     {
       { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS12SafeBag) },
       { SEC_ASN1_OBJECT_ID, offsetof(SEC_PKCS12SafeBag, safeBagType) },
--- a/lib/pkcs12/p12local.h
+++ b/lib/pkcs12/p12local.h
@@ -50,9 +50,11 @@ extern SEC_PKCS12AuthenticatedSafe *sec_
 
 /* conversion from old to new */
 extern SEC_PKCS12DecoderContext *
 sec_PKCS12ConvertOldSafeToNew(PLArenaPool *arena, PK11SlotInfo *slot,
                               PRBool swapUnicode, SECItem *pwitem,
                               void *wincx, SEC_PKCS12SafeContents *safe,
                               SEC_PKCS12Baggage *baggage);
 
+extern PRBool sec_pkcs12_is_pkcs12_pbe_algorithm(SECOidTag algorithm);
+
 #endif
--- a/lib/pkcs12/p12plcy.c
+++ b/lib/pkcs12/p12plcy.c
@@ -19,16 +19,19 @@ typedef struct pkcs12SuiteMapStr {
 
 static pkcs12SuiteMap pkcs12SuiteMaps[] = {
     { SEC_OID_RC4, 40, PKCS12_RC4_40, PR_FALSE, PR_FALSE },
     { SEC_OID_RC4, 128, PKCS12_RC4_128, PR_FALSE, PR_FALSE },
     { SEC_OID_RC2_CBC, 40, PKCS12_RC2_CBC_40, PR_FALSE, PR_TRUE },
     { SEC_OID_RC2_CBC, 128, PKCS12_RC2_CBC_128, PR_FALSE, PR_FALSE },
     { SEC_OID_DES_CBC, 64, PKCS12_DES_56, PR_FALSE, PR_FALSE },
     { SEC_OID_DES_EDE3_CBC, 192, PKCS12_DES_EDE3_168, PR_FALSE, PR_FALSE },
+    { SEC_OID_AES_128_CBC, 128, PKCS12_AES_CBC_128, PR_FALSE, PR_FALSE },
+    { SEC_OID_AES_192_CBC, 192, PKCS12_AES_CBC_192, PR_FALSE, PR_FALSE },
+    { SEC_OID_AES_256_CBC, 256, PKCS12_AES_CBC_256, PR_FALSE, PR_FALSE },
     { SEC_OID_UNKNOWN, 0, PKCS12_NULL, PR_FALSE, PR_FALSE },
     { SEC_OID_UNKNOWN, 0, 0L, PR_FALSE, PR_FALSE }
 };
 
 /* determine if algid is an algorithm which is allowed */
 PRBool
 SEC_PKCS12DecryptionAllowed(SECAlgorithmID *algid)
 {
--- a/lib/pkcs7/p7create.c
+++ b/lib/pkcs7/p7create.c
@@ -1240,8 +1240,61 @@ SEC_PKCS7CreateEncryptedData(SECOidTag a
                                                algorithm, keysize);
     if (rv != SECSuccess) {
         SEC_PKCS7DestroyContentInfo(cinfo);
         return NULL;
     }
 
     return cinfo;
 }
+
+SEC_PKCS7ContentInfo *
+SEC_PKCS7CreateEncryptedDataWithPBEV2(SECOidTag pbe_algorithm,
+                                      SECOidTag cipher_algorithm,
+                                      SECOidTag prf_algorithm,
+                                      int keysize,
+                                      SECKEYGetPasswordKey pwfn, void *pwfn_arg)
+{
+    SEC_PKCS7ContentInfo *cinfo;
+    SECAlgorithmID *algid;
+    SEC_PKCS7EncryptedData *enc_data;
+    SECStatus rv;
+
+    PORT_Assert(SEC_PKCS5IsAlgorithmPBEAlgTag(pbe_algorithm));
+
+    cinfo = sec_pkcs7_create_content_info(SEC_OID_PKCS7_ENCRYPTED_DATA,
+                                          PR_FALSE, pwfn, pwfn_arg);
+    if (cinfo == NULL)
+        return NULL;
+
+    enc_data = cinfo->content.encryptedData;
+    algid = &(enc_data->encContentInfo.contentEncAlg);
+
+    SECAlgorithmID *pbe_algid;
+    pbe_algid = PK11_CreatePBEV2AlgorithmID(pbe_algorithm,
+                                            cipher_algorithm,
+                                            prf_algorithm,
+                                            keysize,
+                                            NSS_PBE_DEFAULT_ITERATION_COUNT,
+                                            NULL);
+    if (pbe_algid == NULL) {
+        rv = SECFailure;
+    } else {
+        rv = SECOID_CopyAlgorithmID(cinfo->poolp, algid, pbe_algid);
+        SECOID_DestroyAlgorithmID(pbe_algid, PR_TRUE);
+    }
+
+    if (rv != SECSuccess) {
+        SEC_PKCS7DestroyContentInfo(cinfo);
+        return NULL;
+    }
+
+    rv = sec_pkcs7_init_encrypted_content_info(&(enc_data->encContentInfo),
+                                               cinfo->poolp,
+                                               SEC_OID_PKCS7_DATA, PR_FALSE,
+                                               cipher_algorithm, keysize);
+    if (rv != SECSuccess) {
+        SEC_PKCS7DestroyContentInfo(cinfo);
+        return NULL;
+    }
+
+    return cinfo;
+}
--- a/lib/pkcs7/secpkcs7.h
+++ b/lib/pkcs7/secpkcs7.h
@@ -282,16 +282,36 @@ extern SEC_PKCS7ContentInfo *SEC_PKCS7Cr
  * An error results in a return value of NULL and an error set.
  * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
  */
 extern SEC_PKCS7ContentInfo *
 SEC_PKCS7CreateEncryptedData(SECOidTag algorithm, int keysize,
                              SECKEYGetPasswordKey pwfn, void *pwfn_arg);
 
 /*
+ * Create an empty PKCS7 encrypted content info.
+ *
+ * Similar to SEC_PKCS7CreateEncryptedData(), but this is capable of
+ * creating encrypted content for PKCS #5 v2 algorithms.
+ *
+ * "pbe_algorithm" specifies the PBE algorithm to use.
+ * "cipher_algorithm" specifies the bulk encryption algorithm to use.
+ * "prf_algorithm" specifies the PRF algorithm which pbe_algorithm uses.
+ *
+ * An error results in a return value of NULL and an error set.
+ * (Retrieve specific errors via PORT_GetError()/XP_GetError().)
+ */
+extern SEC_PKCS7ContentInfo *
+SEC_PKCS7CreateEncryptedDataWithPBEV2(SECOidTag pbe_algorithm,
+                                      SECOidTag cipher_algorithm,
+                                      SECOidTag prf_algorithm,
+                                      int keysize,
+                                      SECKEYGetPasswordKey pwfn, void *pwfn_arg);
+
+/*
  * All of the following things return SECStatus to signal success or failure.
  * Failure should have a more specific error status available via
  * PORT_GetError()/XP_GetError().
  */
 
 /*
  * Add the specified attribute to the authenticated (i.e. signed) attributes
  * of "cinfo" -- "oidtag" describes the attribute and "value" is the
--- a/lib/util/ciferfam.h
+++ b/lib/util/ciferfam.h
@@ -47,13 +47,16 @@
 /* PKCS12 "Cipher Suites" */
 
 #define PKCS12_RC2_CBC_40 (CIPHER_FAMILYID_PKCS12 | 0001)
 #define PKCS12_RC2_CBC_128 (CIPHER_FAMILYID_PKCS12 | 0002)
 #define PKCS12_RC4_40 (CIPHER_FAMILYID_PKCS12 | 0011)
 #define PKCS12_RC4_128 (CIPHER_FAMILYID_PKCS12 | 0012)
 #define PKCS12_DES_56 (CIPHER_FAMILYID_PKCS12 | 0021)
 #define PKCS12_DES_EDE3_168 (CIPHER_FAMILYID_PKCS12 | 0022)
+#define PKCS12_AES_CBC_128 (CIPHER_FAMILYID_PKCS12 | 0031)
+#define PKCS12_AES_CBC_192 (CIPHER_FAMILYID_PKCS12 | 0032)
+#define PKCS12_AES_CBC_256 (CIPHER_FAMILYID_PKCS12 | 0033)
 
 /* SMIME version numbers are negative, to avoid colliding with SSL versions */
 #define SMIME_LIBRARY_VERSION_1_0 -0x0100
 
 #endif /* _CIFERFAM_H_ */
--- a/tests/tools/tools.sh
+++ b/tests/tools/tools.sh
@@ -268,30 +268,30 @@ tools_p12_export_list_import_all_pkcs5v2
     AES-128-CBC \
     AES-192-CBC \
     AES-256-CBC \
     CAMELLIA-128-CBC \
     CAMELLIA-192-CBC \
     CAMELLIA-256-CBC; do
 
 #---------------------------------------------------------------
-# Bug 452464 - pk12util -o fails when -C option specifies AES or
+# Bug 452464 - pk12util -o fails when -C option specifies
 # Camellia ciphers
 # FIXME Restore these to the list
-#    AES-128-CBC, \
-#    AES-192-CBC, \
-#    AES-256-CBC, \
 #    CAMELLIA-128-CBC, \
 #    CAMELLIA-192-CBC, \
 #    CAMELLIA-256-CBC, \
 #  when 452464 is fixed
 #---------------------------------------------------------------  
     for cert_cipher in \
       RC2-CBC \
       DES-EDE3-CBC \
+      AES-128-CBC \
+      AES-192-CBC \
+      AES-256-CBC \
       null; do
 	  export_list_import ${key_cipher} ${cert_cipher}
 	done
   done
 }
 
 ########################################################################
 # Export using the pkcs12v2pbe ciphers for key and certificate encryption.