You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
9.6 KiB
257 lines
9.6 KiB
diff --git a/cmd/pk12util/pk12util.c b/cmd/pk12util/pk12util.c |
|
--- a/cmd/pk12util/pk12util.c |
|
+++ b/cmd/pk12util/pk12util.c |
|
@@ -660,16 +660,27 @@ P12U_ExportPKCS12Object(char *nn, char * |
|
} |
|
|
|
/* Password to use for PKCS12 file. */ |
|
pwitem = P12U_GetP12FilePassword(PR_TRUE, p12FilePw); |
|
if (!pwitem) { |
|
goto loser; |
|
} |
|
|
|
+ /* we are passing UTF8, drop the NULL in the normal password value. |
|
+ * UCS2 conversion will add it back if necessary. This only affects |
|
+ * password > Blocksize of the Hash function and pkcs5v2 pbe (if password |
|
+ * <=Blocksize then the password is zero padded anyway, so an extra NULL |
|
+ * at the end has not effect). This is allows us to work with openssl and |
|
+ * gnutls. Older versions of NSS already fail to decrypt long passwords |
|
+ * in this case, so we aren't breaking anyone with this code */ |
|
+ if ((pwitem->len > 1) && (!pwitem->data[pwitem->len-1])) { |
|
+ pwitem->len--; |
|
+ } |
|
+ |
|
p12cxt = p12u_InitContext(PR_FALSE, outfile); |
|
if (!p12cxt) { |
|
SECU_PrintError(progName, "Initialization failed: %s", outfile); |
|
pk12uErrno = PK12UERR_INIT_FILE; |
|
goto loser; |
|
} |
|
|
|
if (certlist) { |
|
diff --git a/lib/pkcs12/p12local.c b/lib/pkcs12/p12local.c |
|
--- a/lib/pkcs12/p12local.c |
|
+++ b/lib/pkcs12/p12local.c |
|
@@ -903,31 +903,35 @@ sec_pkcs12_find_object(SEC_PKCS12SafeCon |
|
i++; |
|
} |
|
} |
|
|
|
PORT_SetError(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME); |
|
return NULL; |
|
} |
|
|
|
-/* this function converts a password to unicode and encures that the |
|
- * required double 0 byte be placed at the end of the string |
|
+/* this function converts a password to unicode and ensures that the |
|
+ * required double 0 byte be placed at the end of the string (if zeroTerm |
|
+ * is set), or the 0 bytes at the end are dropped (if zeroTerm is not set). |
|
*/ |
|
PRBool |
|
sec_pkcs12_convert_item_to_unicode(PLArenaPool *arena, SECItem *dest, |
|
SECItem *src, PRBool zeroTerm, |
|
PRBool asciiConvert, PRBool toUnicode) |
|
{ |
|
PRBool success = PR_FALSE; |
|
+ int bufferSize; |
|
+ |
|
if (!src || !dest) { |
|
PORT_SetError(SEC_ERROR_INVALID_ARGS); |
|
return PR_FALSE; |
|
} |
|
|
|
- dest->len = src->len * 3 + 2; |
|
+ bufferSize = src->len * 3 + 2; |
|
+ dest->len = bufferSize; |
|
if (arena) { |
|
dest->data = (unsigned char *)PORT_ArenaZAlloc(arena, dest->len); |
|
} else { |
|
dest->data = (unsigned char *)PORT_ZAlloc(dest->len); |
|
} |
|
|
|
if (!dest->data) { |
|
dest->len = 0; |
|
@@ -951,34 +955,44 @@ sec_pkcs12_convert_item_to_unicode(PLAre |
|
if (!arena) { |
|
PORT_Free(dest->data); |
|
dest->data = NULL; |
|
dest->len = 0; |
|
} |
|
return PR_FALSE; |
|
} |
|
|
|
- if ((dest->len >= 2) && |
|
- (dest->data[dest->len - 1] || dest->data[dest->len - 2]) && zeroTerm) { |
|
- if (dest->len + 2 > 3 * src->len) { |
|
- if (arena) { |
|
- dest->data = (unsigned char *)PORT_ArenaGrow(arena, |
|
- dest->data, dest->len, |
|
- dest->len + 2); |
|
- } else { |
|
- dest->data = (unsigned char *)PORT_Realloc(dest->data, |
|
- dest->len + 2); |
|
+ /* in some cases we need to add NULL terminations and in others |
|
+ * we need to drop null terminations */ |
|
+ if (zeroTerm) { |
|
+ /* unicode adds two nulls a the end */ |
|
+ if (toUnicode) { |
|
+ if ((dest->len >= 2) && |
|
+ (dest->data[dest->len - 1] || dest->data[dest->len - 2])) { |
|
+ /* we've already allocated space for these new NULLs */ |
|
+ PORT_Assert(dest->len + 2 <= bufferSize); |
|
+ dest->len += 2; |
|
+ dest->data[dest->len - 1] = dest->data[dest->len - 2] = 0; |
|
} |
|
- |
|
- if (!dest->data) { |
|
- return PR_FALSE; |
|
+ /* ascii/utf-8 adds just 1 */ |
|
+ } else if ((dest->len >= 1) && dest->data[dest->len-1]) { |
|
+ PORT_Assert(dest->len + 1 <= bufferSize); |
|
+ dest->len ++; |
|
+ dest->data[dest->len-1] = 0; |
|
+ } |
|
+ } else { |
|
+ /* handle the drop case, no need to do any allocations here. */ |
|
+ if (toUnicode) { |
|
+ while ((dest->len >=2) && !dest->data[dest->len - 1] && |
|
+ !dest->data[dest->len - 2]) { |
|
+ dest->len -= 2; |
|
} |
|
+ } else while (dest->len && !dest->data[dest->len-1]) { |
|
+ dest->len--; |
|
} |
|
- 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) |
|
{ |
|
@@ -1006,27 +1020,28 @@ sec_pkcs12_is_pkcs12_pbe_algorithm(SECOi |
|
} |
|
} |
|
|
|
/* this function decodes a password from Unicode if necessary, |
|
* according to the PBE algorithm. |
|
* |
|
* we assume that the pwitem is already encoded in Unicode by the |
|
* caller. if the encryption scheme is not the one defined in PKCS |
|
- * #12, decode the pwitem back into UTF-8. */ |
|
+ * #12, decode the pwitem back into UTF-8. NOTE: UTF-8 strings are |
|
+ * used in the PRF without the trailing NULL */ |
|
PRBool |
|
sec_pkcs12_decode_password(PLArenaPool *arena, |
|
SECItem *result, |
|
SECOidTag algorithm, |
|
const SECItem *pwitem) |
|
{ |
|
if (!sec_pkcs12_is_pkcs12_pbe_algorithm(algorithm)) |
|
return sec_pkcs12_convert_item_to_unicode(arena, result, |
|
(SECItem *)pwitem, |
|
- PR_TRUE, PR_FALSE, PR_FALSE); |
|
+ PR_FALSE, PR_FALSE, PR_FALSE); |
|
|
|
return SECITEM_CopyItem(arena, result, pwitem) == SECSuccess; |
|
} |
|
|
|
/* this function encodes a password into Unicode if necessary, |
|
* according to the PBE algorithm. |
|
* |
|
* we assume that the pwitem holds a raw password. if the encryption |
|
diff --git a/tests/common/init.sh b/tests/common/init.sh |
|
--- a/tests/common/init.sh |
|
+++ b/tests/common/init.sh |
|
@@ -78,25 +78,27 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOU |
|
|
|
CERT_EXTENSIONS_DIR=${HOSTDIR}/cert_extensions |
|
STAPLINGDIR=${HOSTDIR}/stapling |
|
NOLOGINDIR=${HOSTDIR}/nologin |
|
SSLGTESTDIR=${HOSTDIR}/ssl_gtests |
|
GTESTDIR=${HOSTDIR}/gtests |
|
|
|
PWFILE=${HOSTDIR}/tests.pw |
|
+ LONGPWFILE=${HOSTDIR}/tests.longpw |
|
EMPTY_FILE=${HOSTDIR}/tests_empty |
|
NOISE_FILE=${HOSTDIR}/tests_noise |
|
CORELIST_FILE=${HOSTDIR}/clist |
|
|
|
FIPSPWFILE=${HOSTDIR}/tests.fipspw |
|
FIPSBADPWFILE=${HOSTDIR}/tests.fipsbadpw |
|
FIPSP12PWFILE=${HOSTDIR}/tests.fipsp12pw |
|
|
|
echo nss > ${PWFILE} |
|
+ echo "nss123456789012345678901234567890123456789012345678901234567890_" > ${LONGPWFILE} |
|
echo > ${EMPTY_FILE} |
|
echo "fIps140" > ${FIPSPWFILE} |
|
echo "fips104" > ${FIPSBADPWFILE} |
|
echo "pKcs12fips140" > ${FIPSP12PWFILE} |
|
|
|
noise |
|
|
|
P_SERVER_CADIR=${SERVER_CADIR} |
|
@@ -656,16 +658,17 @@ if [ -z "${INIT_SOURCED}" -o "${INIT_SOU |
|
P_R_NOLOGINDIR="multiaccess:${D_NOLOGIN}" |
|
P_R_EXT_SERVERDIR="multiaccess:${D_EXT_SERVER}" |
|
P_R_EXT_CLIENTDIR="multiaccess:${D_EXT_CLIENT}" |
|
P_R_IMPLICIT_INIT_DIR="multiaccess:${D_IMPLICIT_INIT}" |
|
P_R_RSAPSSDIR="multiaccess:${D_RSAPSS}" |
|
fi |
|
|
|
R_PWFILE=../tests.pw |
|
+ R_LONGPWFILE=../tests.longpw |
|
R_EMPTY_FILE=../tests_empty |
|
R_NOISE_FILE=../tests_noise |
|
|
|
R_FIPSPWFILE=../tests.fipspw |
|
R_FIPSBADPWFILE=../tests.fipsbadpw |
|
R_FIPSP12PWFILE=../tests.fipsp12pw |
|
|
|
trap "Exit $0 Signal_caught" 2 3 |
|
diff --git a/tests/tools/tools.sh b/tests/tools/tools.sh |
|
--- a/tests/tools/tools.sh |
|
+++ b/tests/tools/tools.sh |
|
@@ -382,16 +382,40 @@ tools_p12_export_list_import_with_defaul |
|
check_tmpfile |
|
|
|
echo "$SCRIPTNAME: Listing Alice's pk12 EC file -----------------" |
|
echo "pk12util -l Alice-ec.p12 -w ${R_PWFILE}" |
|
${BINDIR}/pk12util -l Alice-ec.p12 -w ${R_PWFILE} 2>&1 |
|
ret=$? |
|
html_msg $ret 0 "Listing Alice's pk12 EC file (pk12util -l)" |
|
check_tmpfile |
|
+ |
|
+ echo "$SCRIPTNAME: Exporting Alice's email EC cert & key with long pw------" |
|
+ echo "pk12util -o Alice-ec-long.p12 -n \"Alice-ec\" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \\" |
|
+ echo " -w ${R_LONGPWFILE}" |
|
+ ${BINDIR}/pk12util -o Alice-ec-long.p12 -n "Alice-ec" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \ |
|
+ -w ${R_LONGPWFILE} 2>&1 |
|
+ ret=$? |
|
+ html_msg $ret 0 "Exporting Alice's email EC cert & key with long pw (pk12util -o)" |
|
+ check_tmpfile |
|
+ verify_p12 Alice-ec-long.p12 "default" "default" "default" |
|
+ |
|
+ echo "$SCRIPTNAME: Importing Alice's email EC cert & key with long pw-----" |
|
+ echo "pk12util -i Alice-ec-long.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_LONGPWFILE}" |
|
+ ${BINDIR}/pk12util -i Alice-ec-long.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_LONGPWFILE} 2>&1 |
|
+ ret=$? |
|
+ html_msg $ret 0 "Importing Alice's email EC cert & key with long pw (pk12util -i)" |
|
+ check_tmpfile |
|
+ |
|
+ echo "$SCRIPTNAME: Listing Alice's pk12 EC file with long pw ------------" |
|
+ echo "pk12util -l Alice-ec-long.p12 -w ${R_LONGPWFILE}" |
|
+ ${BINDIR}/pk12util -l Alice-ec-long.p12 -w ${R_LONGPWFILE} 2>&1 |
|
+ ret=$? |
|
+ html_msg $ret 0 "Listing Alice's pk12 EC file with long pw (pk12util -l)" |
|
+ check_tmpfile |
|
} |
|
|
|
tools_p12_import_old_files() |
|
{ |
|
echo "$SCRIPTNAME: Importing PKCS#12 files created with older NSS --------------" |
|
echo "pk12util -i TestOldCA.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}" |
|
${BINDIR}/pk12util -i ${TOOLSDIR}/data/TestOldCA.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE} 2>&1 |
|
ret=$?
|
|
|