Skip to content

Commit

Permalink
Bug 1399867, pkcs12: Add a compat option for password encoding, r=rre…
Browse files Browse the repository at this point in the history
…lyea
  • Loading branch information
ueno committed Sep 14, 2017
1 parent c1b8be4 commit 7519c77
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 9 deletions.
9 changes: 9 additions & 0 deletions lib/nss/nss.h
Expand Up @@ -291,6 +291,15 @@ SECStatus NSS_UnregisterShutdown(NSS_ShutdownFunc sFunc, void *appData);
#define NSS_DTLS_VERSION_MIN_POLICY 0x00a
#define NSS_DTLS_VERSION_MAX_POLICY 0x00b

/* Until NSS 3.30, the PKCS#12 implementation used BMPString encoding
* for all passwords. This changed to use UTF-8 for non-PKCS#12 PBEs
* in NSS 3.31.
*
* For backward compatibility, this option reverts the behavior to the
* old NSS versions. This option might be removed in the future NSS
* releases; don't rely on it. */
#define __NSS_PKCS12_DECODE_FORCE_UNICODE 0x00c

/*
* Set and get global options for the NSS library.
*/
Expand Down
8 changes: 8 additions & 0 deletions lib/nss/nssoptions.c
Expand Up @@ -23,6 +23,7 @@ struct nssOps {
PRInt32 tlsVersionMaxPolicy;
PRInt32 dtlsVersionMinPolicy;
PRInt32 dtlsVersionMaxPolicy;
PRInt32 pkcs12DecodeForceUnicode;
};

static struct nssOps nss_ops = {
Expand All @@ -33,6 +34,7 @@ static struct nssOps nss_ops = {
0xffff, /* set TLS max to more than the largest legal SSL value */
1,
0xffff,
PR_FALSE
};

SECStatus
Expand Down Expand Up @@ -62,6 +64,9 @@ NSS_OptionSet(PRInt32 which, PRInt32 value)
case NSS_DTLS_VERSION_MAX_POLICY:
nss_ops.dtlsVersionMaxPolicy = value;
break;
case __NSS_PKCS12_DECODE_FORCE_UNICODE:
nss_ops.pkcs12DecodeForceUnicode = value;
break;
default:
rv = SECFailure;
}
Expand Down Expand Up @@ -96,6 +101,9 @@ NSS_OptionGet(PRInt32 which, PRInt32 *value)
case NSS_DTLS_VERSION_MAX_POLICY:
*value = nss_ops.dtlsVersionMaxPolicy;
break;
case __NSS_PKCS12_DECODE_FORCE_UNICODE:
*value = nss_ops.pkcs12DecodeForceUnicode;
break;
default:
rv = SECFailure;
}
Expand Down
63 changes: 54 additions & 9 deletions lib/pkcs12/p12d.c
Expand Up @@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nssrenam.h"
#include "nss.h"
#include "p12t.h"
#include "p12.h"
#include "plarena.h"
Expand Down Expand Up @@ -126,6 +127,7 @@ struct SEC_PKCS12DecoderContextStr {
SECKEYGetPasswordKey pwfn;
void *pwfnarg;
PRBool swapUnicodeBytes;
PRBool forceUnicode;

/* import information */
PRBool bagsVerified;
Expand Down Expand Up @@ -192,8 +194,18 @@ sec_pkcs12_decoder_get_decrypt_key(void *arg, SECAlgorithmID *algid)
}

algorithm = SECOID_GetAlgorithmTag(algid);
if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm, p12dcx->pwitem))
return NULL;

if (p12dcx->forceUnicode) {
if (SECITEM_CopyItem(NULL, &pwitem, p12dcx->pwitem) != SECSuccess) {
PK11_FreeSlot(slot);
return NULL;
}
} else {
if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm, p12dcx->pwitem)) {
PK11_FreeSlot(slot);
return NULL;
}
}

bulkKey = PK11_PBEKeyGen(slot, algid, &pwitem, PR_FALSE, p12dcx->wincx);
/* some tokens can't generate PBE keys on their own, generate the
Expand Down Expand Up @@ -1164,6 +1176,8 @@ SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx,
{
SEC_PKCS12DecoderContext *p12dcx;
PLArenaPool *arena;
PRInt32 forceUnicode = PR_FALSE;
SECStatus rv;

arena = PORT_NewArena(2048); /* different size? */
if (!arena) {
Expand Down Expand Up @@ -1196,6 +1210,11 @@ SEC_PKCS12DecoderStart(SECItem *pwitem, PK11SlotInfo *slot, void *wincx,
#else
p12dcx->swapUnicodeBytes = PR_FALSE;
#endif
rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode);
if (rv != SECSuccess) {
goto loser;
}
p12dcx->forceUnicode = forceUnicode;
p12dcx->errorValue = 0;
p12dcx->error = PR_FALSE;

Expand Down Expand Up @@ -2428,7 +2447,7 @@ sec_pkcs12_get_public_value_and_type(SECKEYPublicKey *pubKey, KeyType *type);
static SECStatus
sec_pkcs12_add_key(sec_PKCS12SafeBag *key, SECKEYPublicKey *pubKey,
unsigned int keyUsage,
SECItem *nickName, void *wincx)
SECItem *nickName, PRBool forceUnicode, void *wincx)
{
SECStatus rv;
SECItem *publicValue = NULL;
Expand Down Expand Up @@ -2466,9 +2485,21 @@ sec_pkcs12_add_key(sec_PKCS12SafeBag *key, SECKEYPublicKey *pubKey,
&key->safeBagContent.pkcs8ShroudedKeyBag->algorithm;
SECOidTag algorithm = SECOID_GetAlgorithmTag(algid);

if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm,
key->pwitem))
return SECFailure;
if (forceUnicode) {
if (SECITEM_CopyItem(NULL, &pwitem, key->pwitem) != SECSuccess) {
key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
key->problem = PR_TRUE;
return SECFailure;
}
} else {
if (!sec_pkcs12_decode_password(NULL, &pwitem, algorithm,
key->pwitem)) {
key->error = SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY;
key->problem = PR_TRUE;
return SECFailure;
}
}

rv = PK11_ImportEncryptedPrivateKeyInfo(key->slot,
key->safeBagContent.pkcs8ShroudedKeyBag,
&pwitem, nickName, publicValue,
Expand Down Expand Up @@ -2923,7 +2954,8 @@ sec_pkcs12_get_public_value_and_type(SECKEYPublicKey *pubKey,
* two passes in sec_pkcs12_validate_bags.
*/
static SECStatus
sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, void *wincx)
sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, PRBool forceUnicode,
void *wincx)
{
sec_PKCS12SafeBag **keyList;
int i;
Expand Down Expand Up @@ -2976,7 +3008,8 @@ sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, void *wincx)
key->problem = PR_TRUE;
rv = SECFailure;
} else {
rv = sec_pkcs12_add_key(key, pubKey, keyUsage, nickName, wincx);
rv = sec_pkcs12_add_key(key, pubKey, keyUsage, nickName,
forceUnicode, wincx);
}
if (pubKey) {
SECKEY_DestroyPublicKey(pubKey);
Expand Down Expand Up @@ -3053,6 +3086,9 @@ sec_pkcs12_install_bags(sec_PKCS12SafeBag **safeBags, void *wincx)
SECStatus
SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx)
{
PRBool forceUnicode = PR_FALSE;
SECStatus rv;

if (!p12dcx || p12dcx->error) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
Expand All @@ -3062,7 +3098,16 @@ SEC_PKCS12DecoderImportBags(SEC_PKCS12DecoderContext *p12dcx)
return SECFailure;
}

return sec_pkcs12_install_bags(p12dcx->safeBags, p12dcx->wincx);
/* We need to check the option here as well as in
* SEC_PKCS12DecoderStart, because different PBE's could be used
* for PKCS #7 and PKCS #8 */
rv = NSS_OptionGet(__NSS_PKCS12_DECODE_FORCE_UNICODE, &forceUnicode);
if (rv != SECSuccess) {
return SECFailure;
}

return sec_pkcs12_install_bags(p12dcx->safeBags, forceUnicode,
p12dcx->wincx);
}

PRBool
Expand Down

0 comments on commit 7519c77

Please sign in to comment.