/* 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/. */
/* does the blob authenticate properly? */
rv = SEC_PKCS12DecoderVerify(p12dcx); if (rv != SECSuccess) { if (uniPwp->len == 2) { /* this is a null PW, try once more with a zero-length PW
instead of a null string */
SEC_PKCS12DecoderFinish(p12dcx);
uniPwp->len = 0;
trypw = PR_TRUE;
} elseif (forceUnicode == pk12uForceUnicode) { /* try again with a different password encoding */
forceUnicode = !pk12uForceUnicode;
rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE,
forceUnicode); if (rv != SECSuccess) {
SECU_PrintError(progName, "PKCS12 decoding failed to set option");
pk12uErrno = PK12UERR_DECODEVERIFY; break;
}
SEC_PKCS12DecoderFinish(p12dcx);
trypw = PR_TRUE;
} else {
SECU_PrintError(progName, "PKCS12 decode not verified");
pk12uErrno = PK12UERR_DECODEVERIFY; break;
}
}
} while (trypw == PR_TRUE);
/* revert the option setting */ if (forceUnicode != pk12uForceUnicode) { if (SECSuccess != NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE, pk12uForceUnicode)) {
SECU_PrintError(progName, "PKCS12 decoding failed to set option");
pk12uErrno = PK12UERR_DECODEVERIFY;
rv = SECFailure;
}
} /* rv has been set at this point */
done: /* if we are ignoring Integrity and we failed because we couldn't
* verify the integrity code, go ahead and succeed */ if (rv != SECSuccess && !(ignoreIntegrity &&
(pk12uErrno == PK12UERR_DECODEVERIFY))) { if (p12dcx != NULL) {
SEC_PKCS12DecoderFinish(p12dcx);
p12dcx = NULL;
} if (uniPwp->data) {
SECITEM_ZfreeItem(uniPwp, PR_FALSE);
uniPwp->data = NULL;
}
}
PR_Close(p12cxt->file);
p12cxt->file = NULL; /* PK11_FreeSlot(slot); */
p12u_DestroyContext(&p12cxt, PR_FALSE);
/* * given a filename for pkcs12 file, imports certs and keys * * Change: altitude * I've changed this function so that it takes the keydb and pkcs12 file * passwords from files. The "pwdKeyDB" and "pwdP12File" * variables have been added for this purpose.
*/
PRIntn
P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot,
secuPWData *slotPw, secuPWData *p12FilePw,
PRBool ignoreIntegrity)
{
SEC_PKCS12DecoderContext *p12dcx = NULL;
SECItem uniPwitem = { 0 };
PRBool forceUnicode = pk12uForceUnicode;
PRBool trypw;
SECStatus rv = SECFailure;
rv = P12U_InitSlot(slot, slotPw); if (rv != SECSuccess) {
SECU_PrintError(progName, "Failed to authenticate to \"%s\"",
PK11_GetSlotName(slot));
pk12uErrno = PK12UERR_PK11GETSLOT; return rv;
}
do {
trypw = PR_FALSE; /* normally we do this once */
rv = SECFailure;
p12dcx = p12U_ReadPKCS12File(&uniPwitem, in_file, slot, slotPw,
p12FilePw, ignoreIntegrity);
if (p12dcx == NULL) { goto loser;
}
/* make sure the bags are okey dokey -- nicknames correct, etc. */
rv = SEC_PKCS12DecoderValidateBags(p12dcx, P12U_NicknameCollisionCallback); if (rv != SECSuccess) { if (PORT_GetError() == SEC_ERROR_PKCS12_DUPLICATE_DATA) {
pk12uErrno = PK12UERR_CERTALREADYEXISTS;
} else {
pk12uErrno = PK12UERR_DECODEVALIBAGS;
}
SECU_PrintError(progName, "PKCS12 decode validate bags failed"); goto loser;
}
/* stuff 'em in */ if (forceUnicode != pk12uForceUnicode) {
rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE,
forceUnicode); if (rv != SECSuccess) {
SECU_PrintError(progName, "PKCS12 decode set option failed");
pk12uErrno = PK12UERR_DECODEIMPTBAGS; goto loser;
}
}
rv = SEC_PKCS12DecoderImportBags(p12dcx); if (rv != SECSuccess) { if (PR_GetError() == SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY &&
forceUnicode == pk12uForceUnicode) { /* try again with a different password encoding */
forceUnicode = !pk12uForceUnicode;
SEC_PKCS12DecoderFinish(p12dcx);
SECITEM_ZfreeItem(&uniPwitem, PR_FALSE);
trypw = PR_TRUE;
} else {
SECU_PrintError(progName, "PKCS12 decode import bags failed");
pk12uErrno = PK12UERR_DECODEIMPTBAGS; goto loser;
}
}
} while (trypw);
/* revert the option setting */ if (forceUnicode != pk12uForceUnicode) {
rv = NSS_OptionSet(__NSS_PKCS12_DECODE_FORCE_UNICODE, pk12uForceUnicode); if (rv != SECSuccess) {
SECU_PrintError(progName, "PKCS12 decode set option failed");
pk12uErrno = PK12UERR_DECODEIMPTBAGS; goto loser;
}
}
if (P12U_InitSlot(inSlot, slotPw) != SECSuccess) {
SECU_PrintError(progName, "Failed to authenticate to \"%s\"",
PK11_GetSlotName(inSlot));
pk12uErrno = PK12UERR_PK11GETSLOT; goto loser;
}
certlist = PK11_FindCertsFromNickname(nn, slotPw); if (!certlist) {
PORT_SetError(SEC_ERROR_UNKNOWN_CERT);
SECU_PrintError(progName, "find user certs from nickname failed");
pk12uErrno = PK12UERR_FINDCERTBYNN; return;
}
if ((SECSuccess != CERT_FilterCertListForUserCerts(certlist)) ||
CERT_LIST_EMPTY(certlist)) {
PR_fprintf(PR_STDERR, "%s: no user certs from given nickname\n",
progName);
pk12uErrno = PK12UERR_FINDCERTBYNN; goto loser;
}
/* 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 > 0) && (!pwitem->data[pwitem->len - 1])) {
pwitem->len--;
}
if (certlist) {
CERTCertificate *cert = CERT_LIST_HEAD(certlist)->cert; if (cert) {
slot = cert->slot; /* use the slot from the first matching
certificate to create the context . This is for keygen */
}
} if (!slot) {
SECU_PrintError(progName, "cert does not have a slot");
pk12uErrno = PK12UERR_FINDCERTBYNN; goto loser;
}
p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, slotPw); if (!p12ecx) {
SECU_PrintError(progName, "export context creation failed");
pk12uErrno = PK12UERR_EXPORTCXCREATE; goto loser;
}
for (node = CERT_LIST_HEAD(certlist);
!CERT_LIST_END(node, certlist);
node = CERT_LIST_NEXT(node)) {
CERTCertificate *cert = node->cert; if (!cert->slot) {
SECU_PrintError(progName, "cert does not have a slot");
pk12uErrno = PK12UERR_FINDCERTBYNN; goto loser;
}
for (tag = 1; (oid = SECOID_FindOIDByTag(tag)) != NULL; tag++) { /* only interested in oids that we actually understand */ if (oid->mechanism == CKM_INVALID_MECHANISM) { continue;
} if (PORT_Strcasecmp(oid->desc, cipherString) != 0) { continue;
} return tag;
} return SEC_OID_UNKNOWN;
}
/* * use the oid table description to map a user input string to a particular * oid.
*/
SECOidTag
PKCS12U_MapCipherFromString(char *cipherString, int keyLen)
{
SECOidTag tag;
SECOidTag cipher;
/* future enhancement: provide 'friendlier' typed in names for * pbe mechanisms.
*/
/* look for the oid tag by Description */
tag = PKCS12U_FindTagFromString(cipherString); if (tag == SEC_OID_UNKNOWN) { return tag;
}
cipher = SEC_OID_UNKNOWN; /* we found a match... get the PBE version of this
* cipher... */ if (!SEC_PKCS5IsAlgorithmPBEAlgTag(tag)) {
cipher = SEC_PKCS5GetPBEAlgorithm(tag, keyLen); /* no eqivalent PKCS5/PKCS12 cipher, use the raw * encryption tag we got and pass it directly in,
* pkcs12 will use the pkcsv5 mechanism */ if (cipher == SEC_OID_PKCS5_PBES2) {
cipher = tag;
} elseif (cipher == SEC_OID_PKCS5_PBMAC1) { /* make sure we have not macing ciphers here */
cipher = SEC_OID_UNKNOWN;
}
} else {
cipher = tag;
} return cipher;
}
/* look for the oid tag by Description */
hashAlg = PKCS12U_FindTagFromString(hashString); if (hashAlg == SEC_OID_UNKNOWN) { return hashAlg;
} /* make sure it's a hashing oid */ if (HASH_GetHashTypeByOidTag(hashAlg) == HASH_AlgNULL) { /* allow HMAC here. HMAC implies PKCS 5 v2 pba */
SECOidTag baseHashAlg = HASH_GetHashOidTagByHMACOidTag(hashAlg); if (baseHashAlg == SEC_OID_UNKNOWN) { /* not an hmac either, reject the entry */ return SEC_OID_UNKNOWN;
}
} return hashAlg;
}
/* setup unicode callback functions */
PORT_SetUCS2_ASCIIConversionFunction(p12u_ucs2_ascii_conversion_function); /* use the defaults for UCS4-UTF8 and UCS2-UTF8 */
/* ciphers are already enabled by default, allow policy to work */ /* p12u_EnableAllCiphers(); */
if (pk12util.options[opt_Cipher].activated) { char *cipherString = pk12util.options[opt_Cipher].arg;
cipher = PKCS12U_MapCipherFromString(cipherString, keyLen); /* We only want encryption PBE's. make sure we don't have
* any MAC pbes */ if (cipher == SEC_OID_UNKNOWN) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString);
pk12uErrno = PK12UERR_INVALIDALGORITHM; goto done;
}
}
if (pk12util.options[opt_CertCipher].activated) { char *cipherString = pk12util.options[opt_CertCipher].arg;
if (PORT_Strcasecmp(cipherString, "none") == 0) {
certCipher = SEC_OID_UNKNOWN;
} else {
certCipher = PKCS12U_MapCipherFromString(cipherString, certKeyLen); /* If the user requested a cipher and we didn't find it, then
* don't just silently not encrypt. */ if (certCipher == SEC_OID_UNKNOWN) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
SECU_PrintError(progName, "Algorithm: \"%s\"", cipherString);
pk12uErrno = PK12UERR_INVALIDALGORITHM; goto done;
}
}
} /* in FIPS mode default to encoding with pkcs5v2 for the MAC */ if (PK11_IsFIPS()) {
hash = SEC_OID_HMAC_SHA256;
} if (pk12util.options[opt_Mac].activated) { char *hashString = pk12util.options[opt_Mac].arg;
hash = PKCS12U_MapHashFromString(hashString); /* We don't support creating Mac-less pkcs 12 files */ if (hash == SEC_OID_UNKNOWN) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
SECU_PrintError(progName, "Algorithm: \"%s\"", hashString);
pk12uErrno = PK12UERR_INVALIDALGORITHM; goto done;
}
}
if (pk12util.options[opt_Import].activated) {
P12U_ImportPKCS12Object(import_file, slot, &slotPw, &p12FilePw,
ignoreIntegrity);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.