diff options
Diffstat (limited to 'security/nss/lib/crmf/crmfcont.c')
-rw-r--r-- | security/nss/lib/crmf/crmfcont.c | 1165 |
1 files changed, 0 insertions, 1165 deletions
diff --git a/security/nss/lib/crmf/crmfcont.c b/security/nss/lib/crmf/crmfcont.c deleted file mode 100644 index 3948023c2..000000000 --- a/security/nss/lib/crmf/crmfcont.c +++ /dev/null @@ -1,1165 +0,0 @@ -/* -*- Mode: C; tab-width: 8 -*-*/ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1994-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -#include "crmf.h" -#include "crmfi.h" -#include "pk11func.h" -#include "keyhi.h" -#include "secoid.h" - -static SECStatus -crmf_modify_control_array (CRMFCertRequest *inCertReq, int count) -{ - if (count > 0) { - void *dummy = PORT_Realloc(inCertReq->controls, - sizeof(CRMFControl*)*(count+2)); - if (dummy == NULL) { - return SECFailure; - } - inCertReq->controls = dummy; - } else { - inCertReq->controls = PORT_ZNewArray(CRMFControl*, 2); - } - return (inCertReq->controls == NULL) ? SECFailure : SECSuccess ; -} - -static SECStatus -crmf_add_new_control(CRMFCertRequest *inCertReq,SECOidTag inTag, - CRMFControl **destControl) -{ - SECOidData *oidData; - SECStatus rv; - PRArenaPool *poolp; - int numControls = 0; - CRMFControl *newControl; - CRMFControl **controls; - void *mark; - - poolp = inCertReq->poolp; - if (poolp == NULL) { - return SECFailure; - } - mark = PORT_ArenaMark(poolp); - if (inCertReq->controls != NULL) { - while (inCertReq->controls[numControls] != NULL) - numControls++; - } - rv = crmf_modify_control_array(inCertReq, numControls); - if (rv != SECSuccess) { - goto loser; - } - controls = inCertReq->controls; - oidData = SECOID_FindOIDByTag(inTag); - newControl = *destControl = PORT_ArenaZNew(poolp,CRMFControl); - if (newControl == NULL) { - goto loser; - } - rv = SECITEM_CopyItem(poolp, &newControl->derTag, &oidData->oid); - if (rv != SECSuccess) { - goto loser; - } - newControl->tag = inTag; - controls[numControls] = newControl; - controls[numControls+1] = NULL; - PORT_ArenaUnmark(poolp, mark); - return SECSuccess; - - loser: - PORT_ArenaRelease(poolp, mark); - *destControl = NULL; - return SECFailure; - -} - -SECStatus -crmf_add_secitem_control(CRMFCertRequest *inCertReq, SECItem *value, - SECOidTag inTag) -{ - SECStatus rv; - CRMFControl *newControl; - void *mark; - - rv = crmf_add_new_control(inCertReq, inTag, &newControl); - if (rv != SECSuccess) { - return rv; - } - mark = PORT_ArenaMark(inCertReq->poolp); - rv = SECITEM_CopyItem(inCertReq->poolp, &newControl->derValue, value); - if (rv != SECSuccess) { - PORT_ArenaRelease(inCertReq->poolp, mark); - return rv; - } - PORT_ArenaUnmark(inCertReq->poolp, mark); - return SECSuccess; -} - -SECStatus -CRMF_CertRequestSetRegTokenControl(CRMFCertRequest *inCertReq, SECItem *value) -{ - return crmf_add_secitem_control(inCertReq, value, - SEC_OID_PKIX_REGCTRL_REGTOKEN); -} - -SECStatus -CRMF_CertRequestSetAuthenticatorControl (CRMFCertRequest *inCertReq, - SECItem *value) -{ - return crmf_add_secitem_control(inCertReq, value, - SEC_OID_PKIX_REGCTRL_AUTHENTICATOR); -} - -SECStatus -crmf_destroy_encrypted_value(CRMFEncryptedValue *inEncrValue, PRBool freeit) -{ - if (inEncrValue != NULL) { - if (inEncrValue->intendedAlg) { - SECOID_DestroyAlgorithmID(inEncrValue->intendedAlg, PR_TRUE); - } - if (inEncrValue->symmAlg) { - SECOID_DestroyAlgorithmID(inEncrValue->symmAlg, PR_TRUE); - } - if (inEncrValue->encSymmKey.data) { - PORT_Free(inEncrValue->encSymmKey.data); - } - if (inEncrValue->keyAlg) { - SECOID_DestroyAlgorithmID(inEncrValue->keyAlg, PR_TRUE); - } - if (inEncrValue->valueHint.data) { - PORT_Free(inEncrValue->valueHint.data); - } - if (inEncrValue->encValue.data) { - PORT_Free(inEncrValue->encValue.data); - } - if (freeit) { - PORT_Free(inEncrValue); - } - } - return SECSuccess; -} - -SECStatus -CRMF_DestroyEncryptedValue(CRMFEncryptedValue *inEncrValue) -{ - return crmf_destroy_encrypted_value(inEncrValue, PR_TRUE); -} - -SECStatus -crmf_copy_encryptedvalue_secalg(PRArenaPool *poolp, - SECAlgorithmID *srcAlgId, - SECAlgorithmID **destAlgId) -{ - SECAlgorithmID *newAlgId; - - *destAlgId = newAlgId = (poolp != NULL) ? - PORT_ArenaZNew(poolp, SECAlgorithmID) : - PORT_ZNew(SECAlgorithmID); - if (newAlgId == NULL) { - return SECFailure; - } - - return SECOID_CopyAlgorithmID(poolp, newAlgId, srcAlgId); -} - -SECStatus -crmf_copy_encryptedvalue(PRArenaPool *poolp, - CRMFEncryptedValue *srcValue, - CRMFEncryptedValue *destValue) -{ - SECStatus rv; - - if (srcValue->intendedAlg != NULL) { - rv = crmf_copy_encryptedvalue_secalg(poolp, - srcValue->intendedAlg, - &destValue->intendedAlg); - if (rv != SECSuccess) { - goto loser; - } - } - if (srcValue->symmAlg != NULL) { - rv = crmf_copy_encryptedvalue_secalg(poolp, - srcValue->symmAlg, - &destValue->symmAlg); - if (rv != SECSuccess) { - goto loser; - } - } - if (srcValue->encSymmKey.data != NULL) { - rv = crmf_make_bitstring_copy(poolp, - &destValue->encSymmKey, - &srcValue->encSymmKey); - if (rv != SECSuccess) { - goto loser; - } - } - if (srcValue->keyAlg != NULL) { - rv = crmf_copy_encryptedvalue_secalg(poolp, - srcValue->keyAlg, - &destValue->keyAlg); - if (rv != SECSuccess) { - goto loser; - } - } - if (srcValue->valueHint.data != NULL) { - rv = SECITEM_CopyItem(poolp, - &destValue->valueHint, - &srcValue->valueHint); - if (rv != SECSuccess) { - goto loser; - } - } - if (srcValue->encValue.data != NULL) { - rv = crmf_make_bitstring_copy(poolp, - &destValue->encValue, - &srcValue->encValue); - if (rv != SECSuccess) { - goto loser; - } - } - return SECSuccess; - loser: - if (poolp == NULL && destValue != NULL) { - crmf_destroy_encrypted_value(destValue, PR_TRUE); - } - return SECFailure; -} - -SECStatus -crmf_copy_encryptedkey(PRArenaPool *poolp, - CRMFEncryptedKey *srcEncrKey, - CRMFEncryptedKey *destEncrKey) -{ - SECStatus rv; - void *mark; - - if (poolp != NULL) { - mark = PORT_ArenaMark(poolp); - } - - switch (srcEncrKey->encKeyChoice) { - case crmfEncryptedValueChoice: - rv = crmf_copy_encryptedvalue(poolp, - &srcEncrKey->value.encryptedValue, - &destEncrKey->value.encryptedValue); - break; - case crmfEnvelopedDataChoice: - destEncrKey->value.envelopedData = - SEC_PKCS7CopyContentInfo(srcEncrKey->value.envelopedData); - rv = (destEncrKey->value.envelopedData != NULL) ? SECSuccess: - SECFailure; - break; - default: - rv = SECFailure; - } - if (rv != SECSuccess) { - goto loser; - } - destEncrKey->encKeyChoice = srcEncrKey->encKeyChoice; - if (poolp != NULL) { - PORT_ArenaUnmark(poolp, mark); - } - return SECSuccess; - - loser: - if (poolp != NULL) { - PORT_ArenaRelease(poolp, mark); - } - return SECFailure; -} - -CRMFPKIArchiveOptions* -crmf_create_encr_pivkey_option(CRMFEncryptedKey *inEncryptedKey) -{ - CRMFPKIArchiveOptions *newArchOpt; - SECStatus rv; - - newArchOpt = PORT_ZNew(CRMFPKIArchiveOptions); - if (newArchOpt == NULL) { - goto loser; - } - - rv = crmf_copy_encryptedkey(NULL, inEncryptedKey, - &newArchOpt->option.encryptedKey); - - if (rv != SECSuccess) { - goto loser; - } - newArchOpt->archOption = crmfEncryptedPrivateKey; - return newArchOpt; - loser: - if (newArchOpt != NULL) { - CRMF_DestroyPKIArchiveOptions(newArchOpt); - } - return NULL; -} - -static CRMFPKIArchiveOptions* -crmf_create_keygen_param_option(SECItem *inKeyGenParams) -{ - CRMFPKIArchiveOptions *newArchOptions; - SECStatus rv; - - newArchOptions = PORT_ZNew(CRMFPKIArchiveOptions); - if (newArchOptions == NULL) { - goto loser; - } - newArchOptions->archOption = crmfKeyGenParameters; - rv = SECITEM_CopyItem(NULL, &newArchOptions->option.keyGenParameters, - inKeyGenParams); - if (rv != SECSuccess) { - goto loser; - } - return newArchOptions; - loser: - if (newArchOptions != NULL) { - CRMF_DestroyPKIArchiveOptions(newArchOptions); - } - return NULL; -} - -static CRMFPKIArchiveOptions* -crmf_create_arch_rem_gen_privkey(PRBool archiveRemGenPrivKey) -{ - unsigned char value; - SECItem *dummy; - CRMFPKIArchiveOptions *newArchOptions; - - value = (archiveRemGenPrivKey) ? hexTrue : hexFalse; - newArchOptions = PORT_ZNew(CRMFPKIArchiveOptions); - if (newArchOptions == NULL) { - goto loser; - } - dummy = SEC_ASN1EncodeItem(NULL, - &newArchOptions->option.archiveRemGenPrivKey, - &value, SEC_BooleanTemplate); - PORT_Assert (dummy == &newArchOptions->option.archiveRemGenPrivKey); - if (dummy != &newArchOptions->option.archiveRemGenPrivKey) { - SECITEM_FreeItem (dummy, PR_TRUE); - goto loser; - } - newArchOptions->archOption = crmfArchiveRemGenPrivKey; - return newArchOptions; - loser: - if (newArchOptions != NULL) { - CRMF_DestroyPKIArchiveOptions(newArchOptions); - } - return NULL; -} - -CRMFPKIArchiveOptions* -CRMF_CreatePKIArchiveOptions(CRMFPKIArchiveOptionsType inType, void *data) -{ - CRMFPKIArchiveOptions* retOptions; - - PORT_Assert(data != NULL); - if (data == NULL) { - return NULL; - } - switch(inType) { - case crmfEncryptedPrivateKey: - retOptions = crmf_create_encr_pivkey_option((CRMFEncryptedKey*)data); - break; - case crmfKeyGenParameters: - retOptions = crmf_create_keygen_param_option((SECItem*)data); - break; - case crmfArchiveRemGenPrivKey: - retOptions = crmf_create_arch_rem_gen_privkey(*(PRBool*)data); - break; - default: - retOptions = NULL; - } - return retOptions; -} - -static SECStatus -crmf_destroy_encrypted_key(CRMFEncryptedKey *inEncrKey, PRBool freeit) -{ - PORT_Assert(inEncrKey != NULL); - if (inEncrKey != NULL) { - switch (inEncrKey->encKeyChoice){ - case crmfEncryptedValueChoice: - crmf_destroy_encrypted_value(&inEncrKey->value.encryptedValue, - PR_FALSE); - break; - case crmfEnvelopedDataChoice: - SEC_PKCS7DestroyContentInfo(inEncrKey->value.envelopedData); - break; - default: - break; - } - if (freeit) { - PORT_Free(inEncrKey); - } - } - return SECSuccess; -} - -SECStatus -crmf_destroy_pkiarchiveoptions(CRMFPKIArchiveOptions *inArchOptions, - PRBool freeit) -{ - PORT_Assert(inArchOptions != NULL); - if (inArchOptions != NULL) { - switch (inArchOptions->archOption) { - case crmfEncryptedPrivateKey: - crmf_destroy_encrypted_key(&inArchOptions->option.encryptedKey, - PR_FALSE); - break; - case crmfKeyGenParameters: - case crmfArchiveRemGenPrivKey: - /* This is a union, so having a pointer to one is like - * having a pointer to both. - */ - SECITEM_FreeItem(&inArchOptions->option.keyGenParameters, - PR_FALSE); - break; - case crmfNoArchiveOptions: - break; - } - if (freeit) { - PORT_Free(inArchOptions); - } - } - return SECSuccess; -} - -SECStatus -CRMF_DestroyPKIArchiveOptions(CRMFPKIArchiveOptions *inArchOptions) -{ - return crmf_destroy_pkiarchiveoptions(inArchOptions, PR_TRUE); -} - -static CK_MECHANISM_TYPE -crmf_get_non_pad_mechanism(CK_MECHANISM_TYPE type) -{ - switch (type) { - case CKM_DES3_CBC_PAD: - return CKM_DES3_CBC; - case CKM_CAST5_CBC_PAD: - return CKM_CAST5_CBC; - case CKM_DES_CBC_PAD: - return CKM_DES_CBC; - case CKM_IDEA_CBC_PAD: - return CKM_IDEA_CBC; - case CKM_CAST3_CBC_PAD: - return CKM_CAST3_CBC; - case CKM_CAST_CBC_PAD: - return CKM_CAST_CBC; - case CKM_RC5_CBC_PAD: - return CKM_RC5_CBC; - case CKM_RC2_CBC_PAD: - return CKM_RC2_CBC; - case CKM_CDMF_CBC_PAD: - return CKM_CDMF_CBC; - } - return type; -} - -static CK_MECHANISM_TYPE -crmf_get_pad_mech_from_tag(SECOidTag oidTag) -{ - CK_MECHANISM_TYPE mechType; - SECOidData *oidData; - - oidData = SECOID_FindOIDByTag(oidTag); - mechType = (CK_MECHANISM_TYPE)oidData->mechanism; - return PK11_GetPadMechanism(mechType); -} - -static CK_MECHANISM_TYPE -crmf_get_best_privkey_wrap_mechanism(PK11SlotInfo *slot) -{ - CK_MECHANISM_TYPE privKeyPadMechs[] = { CKM_DES3_CBC_PAD, - CKM_CAST5_CBC_PAD, - CKM_DES_CBC_PAD, - CKM_IDEA_CBC_PAD, - CKM_CAST3_CBC_PAD, - CKM_CAST_CBC_PAD, - CKM_RC5_CBC_PAD, - CKM_RC2_CBC_PAD, - CKM_CDMF_CBC_PAD }; - int mechCount = sizeof(privKeyPadMechs)/sizeof(privKeyPadMechs[0]); - int i; - - for (i=0; i < mechCount; i++) { - if (PK11_DoesMechanism(slot, privKeyPadMechs[i])) { - return privKeyPadMechs[i]; - } - } - return CKM_INVALID_MECHANISM; -} - -CK_MECHANISM_TYPE -CRMF_GetBestWrapPadMechanism(PK11SlotInfo *slot) -{ - return crmf_get_best_privkey_wrap_mechanism(slot); -} - -static SECItem* -crmf_get_iv(CK_MECHANISM_TYPE mechType) -{ - int iv_size = PK11_GetIVLength(mechType); - SECItem *iv; - SECStatus rv; - - iv = PORT_ZNew(SECItem); - if (iv == NULL) { - return NULL; - } - if (iv_size == 0) { - iv->data = NULL; - iv->len = 0; - return iv; - } - iv->data = PORT_NewArray(unsigned char, iv_size); - if (iv->data == NULL) { - iv->len = 0; - return iv; - } - iv->len = iv_size; - rv = PK11_GenerateRandom(iv->data, iv->len); - if (rv != SECSuccess) { - PORT_Free(iv->data); - iv->data = NULL; - iv->len = 0; - } - return iv; -} - -SECItem* -CRMF_GetIVFromMechanism(CK_MECHANISM_TYPE mechType) -{ - return crmf_get_iv(mechType); -} - -CK_MECHANISM_TYPE -crmf_get_mechanism_from_public_key(SECKEYPublicKey *inPubKey) -{ - CERTSubjectPublicKeyInfo *spki = NULL; - SECOidTag tag; - - - spki = SECKEY_CreateSubjectPublicKeyInfo(inPubKey); - if (spki == NULL) { - return CKM_INVALID_MECHANISM; - } - tag = SECOID_FindOIDTag(&spki->algorithm.algorithm); - SECKEY_DestroySubjectPublicKeyInfo(spki); - spki = NULL; - return PK11_AlgtagToMechanism(tag); -} - -SECItem* -crmf_get_public_value(SECKEYPublicKey *pubKey, SECItem *dest) -{ - SECItem *pubValue; - - if (dest != NULL) { - pubValue = dest; - } else { - pubValue = PORT_ZNew(SECItem); - } - switch(pubKey->keyType) { - case dsaKey: - SECITEM_CopyItem(NULL, pubValue, &pubKey->u.dsa.publicValue); - break; - case rsaKey: - SECITEM_CopyItem(NULL, pubValue, &pubKey->u.rsa.modulus); - break; - case dhKey: - SECITEM_CopyItem(NULL, pubValue, &pubKey->u.dh.publicValue); - break; - default: - if (dest == NULL) { - PORT_Free(pubValue); - } - pubValue = NULL; - break; - } - return pubValue; -} - -static SECItem* -crmf_decode_params(SECItem *inParams) -{ - SECItem *params; - SECStatus rv; - - params = PORT_ZNew(SECItem); - rv = SEC_ASN1DecodeItem(NULL, params, - SEC_ASN1_GET(SEC_OctetStringTemplate), - inParams); - if (rv != SECSuccess) { - SECITEM_FreeItem(params, PR_TRUE); - return NULL; - } - return params; -} - -int -crmf_get_key_size_from_mech(CK_MECHANISM_TYPE mechType) -{ - CK_MECHANISM_TYPE keyGen = PK11_GetKeyGen(mechType); - - switch (keyGen) { - case CKM_CDMF_KEY_GEN: - case CKM_DES_KEY_GEN: - return 8; - case CKM_DES2_KEY_GEN: - return 16; - case CKM_DES3_KEY_GEN: - return 24; - } - return 0; -} - -SECStatus -crmf_encrypted_value_unwrap_priv_key(PRArenaPool *poolp, - CRMFEncryptedValue *encValue, - SECKEYPrivateKey *privKey, - SECKEYPublicKey *newPubKey, - SECItem *nickname, - PK11SlotInfo *slot, - unsigned char keyUsage, - SECKEYPrivateKey **unWrappedKey, - void *wincx) -{ - PK11SymKey *wrappingKey = NULL; - CK_MECHANISM_TYPE wrapMechType; - SECOidTag oidTag; - SECItem *params = NULL, *publicValue = NULL; - int keySize, origLen; - CK_KEY_TYPE keyType; - CK_ATTRIBUTE_TYPE *usage; - CK_ATTRIBUTE_TYPE rsaUsage[] = { - CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER }; - CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN }; - CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE }; - int usageCount; - - oidTag = SECOID_GetAlgorithmTag(encValue->symmAlg); - wrapMechType = crmf_get_pad_mech_from_tag(oidTag); - keySize = crmf_get_key_size_from_mech(wrapMechType); - wrappingKey = PK11_PubUnwrapSymKey(privKey, &encValue->encSymmKey, - wrapMechType, CKA_UNWRAP, keySize); - if (wrappingKey == NULL) { - goto loser; - }/* Make the length a byte length instead of bit length*/ - params = (encValue->symmAlg != NULL) ? - crmf_decode_params(&encValue->symmAlg->parameters) : NULL; - origLen = encValue->encValue.len; - encValue->encValue.len = CRMF_BITS_TO_BYTES(origLen); - publicValue = crmf_get_public_value(newPubKey, NULL); - switch(newPubKey->keyType) { - default: - case rsaKey: - keyType = CKK_RSA; - switch (keyUsage & (KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE)) { - case KU_KEY_ENCIPHERMENT: - usage = rsaUsage; - usageCount = 2; - break; - case KU_DIGITAL_SIGNATURE: - usage = &rsaUsage[2]; - usageCount = 2; - break; - case KU_KEY_ENCIPHERMENT|KU_DIGITAL_SIGNATURE: - case 0: /* default to everything */ - usage = rsaUsage; - usageCount = 4; - break; - } - break; - case dhKey: - keyType = CKK_DH; - usage = dhUsage; - usageCount = sizeof(dhUsage)/sizeof(dhUsage[0]); - break; - case dsaKey: - keyType = CKK_DSA; - usage = dsaUsage; - usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]); - break; - } - *unWrappedKey = PK11_UnwrapPrivKey(slot, wrappingKey, wrapMechType, params, - &encValue->encValue, nickname, - publicValue, PR_TRUE,PR_TRUE, - keyType, usage, usageCount, wincx); - encValue->encValue.len = origLen; - if (*unWrappedKey == NULL) { - goto loser; - } - SECITEM_FreeItem (publicValue, PR_TRUE); - if (params!= NULL) { - SECITEM_FreeItem(params, PR_TRUE); - } - PK11_FreeSymKey(wrappingKey); - return SECSuccess; - loser: - *unWrappedKey = NULL; - return SECFailure; -} - -CRMFEncryptedValue * -crmf_create_encrypted_value_wrapped_privkey(SECKEYPrivateKey *inPrivKey, - SECKEYPublicKey *inCAKey, - CRMFEncryptedValue *destValue) -{ - SECItem wrappedPrivKey, wrappedSymKey; - SECItem encodedParam, *dummy; - SECStatus rv; - CK_MECHANISM_TYPE pubMechType, symKeyType; - unsigned char *wrappedSymKeyBits; - unsigned char *wrappedPrivKeyBits; - SECItem *iv = NULL; - SECOidTag tag; - PK11SymKey *symKey; - PK11SlotInfo *slot; - SECAlgorithmID *symmAlg; - CRMFEncryptedValue *myEncrValue = NULL; - - encodedParam.data = NULL; - wrappedSymKeyBits = PORT_NewArray(unsigned char, MAX_WRAPPED_KEY_LEN); - wrappedPrivKeyBits = PORT_NewArray(unsigned char, MAX_WRAPPED_KEY_LEN); - if (wrappedSymKeyBits == NULL || wrappedPrivKeyBits == NULL) { - goto loser; - } - if (destValue == NULL) { - myEncrValue = destValue = PORT_ZNew(CRMFEncryptedValue); - if (destValue == NULL) { - goto loser; - } - } - - pubMechType = crmf_get_mechanism_from_public_key(inCAKey); - if (pubMechType == CKM_INVALID_MECHANISM) { - /* XXX I should probably do something here for non-RSA - * keys that are in certs. (ie DSA) - */ - goto loser; - } - slot = inPrivKey->pkcs11Slot; - PORT_Assert(slot != NULL); - symKeyType = crmf_get_best_privkey_wrap_mechanism(slot); - symKey = PK11_KeyGen(slot, symKeyType, NULL, 0, NULL); - if (symKey == NULL) { - goto loser; - } - - wrappedSymKey.data = wrappedSymKeyBits; - wrappedSymKey.len = MAX_WRAPPED_KEY_LEN; - rv = PK11_PubWrapSymKey(pubMechType, inCAKey, symKey, &wrappedSymKey); - if (rv != SECSuccess) { - goto loser; - } - /* Make the length of the result a Bit String length. */ - wrappedSymKey.len <<= 3; - - wrappedPrivKey.data = wrappedPrivKeyBits; - wrappedPrivKey.len = MAX_WRAPPED_KEY_LEN; - iv = crmf_get_iv(symKeyType); - rv = PK11_WrapPrivKey(slot, symKey, inPrivKey, symKeyType, iv, - &wrappedPrivKey, NULL); - PK11_FreeSymKey(symKey); - if (rv != SECSuccess) { - goto loser; - } - /* Make the length of the result a Bit String length. */ - wrappedPrivKey.len <<= 3; - rv = crmf_make_bitstring_copy(NULL, - &destValue->encValue, - &wrappedPrivKey); - if (rv != SECSuccess) { - goto loser; - } - - rv = crmf_make_bitstring_copy(NULL, - &destValue->encSymmKey, - &wrappedSymKey); - if (rv != SECSuccess) { - goto loser; - } - destValue->symmAlg = symmAlg = PORT_ZNew(SECAlgorithmID); - if (symmAlg == NULL) { - goto loser; - } - - dummy = SEC_ASN1EncodeItem(NULL, &encodedParam, iv, - SEC_ASN1_GET(SEC_OctetStringTemplate)); - if (dummy != &encodedParam) { - SECITEM_FreeItem(dummy, PR_TRUE); - goto loser; - } - - symKeyType = crmf_get_non_pad_mechanism(symKeyType); - tag = PK11_MechanismToAlgtag(symKeyType); - rv = SECOID_SetAlgorithmID(NULL, symmAlg, tag, &encodedParam); - if (rv != SECSuccess) { - goto loser; - } - PORT_Free(encodedParam.data); - PORT_Free(wrappedPrivKeyBits); - PORT_Free(wrappedSymKeyBits); - if (iv->data != NULL) { - PORT_Free(iv->data); - } - PORT_Free(iv); - return destValue; - loser: - if (iv != NULL) { - if (iv->data) { - PORT_Free(iv->data); - } - PORT_Free(iv); - } - if (myEncrValue != NULL) { - crmf_destroy_encrypted_value(myEncrValue, PR_TRUE); - } - if (wrappedSymKeyBits != NULL) { - PORT_Free(wrappedSymKeyBits); - } - if (wrappedPrivKeyBits != NULL) { - PORT_Free(wrappedPrivKeyBits); - } - if (encodedParam.data != NULL) { - PORT_Free(encodedParam.data); - } - return NULL; -} - -CRMFEncryptedKey* -CRMF_CreateEncryptedKeyWithEncryptedValue (SECKEYPrivateKey *inPrivKey, - CERTCertificate *inCACert) -{ - SECKEYPublicKey *caPubKey = NULL; - CRMFEncryptedKey *encKey = NULL; - CRMFEncryptedValue *dummy; - - PORT_Assert(inPrivKey != NULL && inCACert != NULL); - if (inPrivKey == NULL || inCACert == NULL) { - return NULL; - } - - caPubKey = CERT_ExtractPublicKey(inCACert); - if (caPubKey == NULL) { - goto loser; - } - - encKey = PORT_ZNew(CRMFEncryptedKey); - if (encKey == NULL) { - goto loser; - } - dummy = crmf_create_encrypted_value_wrapped_privkey(inPrivKey, - caPubKey, - &encKey->value.encryptedValue); - PORT_Assert(dummy == &encKey->value.encryptedValue); - /* We won't add the der value here, but rather when it - * becomes part of a certificate request. - */ - SECKEY_DestroyPublicKey(caPubKey); - encKey->encKeyChoice = crmfEncryptedValueChoice; - return encKey; - loser: - if (encKey != NULL) { - CRMF_DestroyEncryptedKey(encKey); - } - if (caPubKey != NULL) { - SECKEY_DestroyPublicKey(caPubKey); - } - return NULL; -} - -SECStatus -CRMF_DestroyEncryptedKey(CRMFEncryptedKey *inEncrKey) -{ - return crmf_destroy_encrypted_key(inEncrKey, PR_TRUE); -} - -SECStatus -crmf_copy_pkiarchiveoptions(PRArenaPool *poolp, - CRMFPKIArchiveOptions *destOpt, - CRMFPKIArchiveOptions *srcOpt) -{ - SECStatus rv; - destOpt->archOption = srcOpt->archOption; - switch (srcOpt->archOption) { - case crmfEncryptedPrivateKey: - rv = crmf_copy_encryptedkey(poolp, - &srcOpt->option.encryptedKey, - &destOpt->option.encryptedKey); - break; - case crmfKeyGenParameters: - case crmfArchiveRemGenPrivKey: - /* We've got a union, so having a pointer to one is just - * like having a pointer to the other one. - */ - rv = SECITEM_CopyItem(poolp, - &destOpt->option.keyGenParameters, - &srcOpt->option.keyGenParameters); - break; - default: - rv = SECFailure; - } - return rv; -} - -static SECStatus -crmf_check_and_adjust_archoption(CRMFControl *inControl) -{ - CRMFPKIArchiveOptions *options; - - options = &inControl->value.archiveOptions; - if (options->archOption == crmfNoArchiveOptions) { - /* It hasn't been set, so figure it out from the - * der. - */ - switch (inControl->derValue.data[0] & 0x0f) { - case 0: - options->archOption = crmfEncryptedPrivateKey; - break; - case 1: - options->archOption = crmfKeyGenParameters; - break; - case 2: - options->archOption = crmfArchiveRemGenPrivKey; - break; - default: - /* We've got bad DER. Return an error. */ - return SECFailure; - } - } - return SECSuccess; -} - -static const SEC_ASN1Template * -crmf_get_pkiarchive_subtemplate(CRMFControl *inControl) -{ - const SEC_ASN1Template *retTemplate; - SECStatus rv; - /* - * We could be in the process of decoding, in which case the - * archOption field will not be set. Let's check it and set - * it accordingly. - */ - - rv = crmf_check_and_adjust_archoption(inControl); - if (rv != SECSuccess) { - return NULL; - } - - switch (inControl->value.archiveOptions.archOption) { - case crmfEncryptedPrivateKey: - retTemplate = CRMFEncryptedKeyWithEncryptedValueTemplate; - inControl->value.archiveOptions.option.encryptedKey.encKeyChoice = - crmfEncryptedValueChoice; - break; - default: - retTemplate = NULL; - } - return retTemplate; -} - -const SEC_ASN1Template* -crmf_get_pkiarchiveoptions_subtemplate(CRMFControl *inControl) -{ - const SEC_ASN1Template *retTemplate; - - switch (inControl->tag) { - case SEC_OID_PKIX_REGCTRL_REGTOKEN: - case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR: - retTemplate = SEC_UTF8StringTemplate; - break; - case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS: - retTemplate = crmf_get_pkiarchive_subtemplate(inControl); - break; - case SEC_OID_PKIX_REGCTRL_PKIPUBINFO: - case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID: - case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY: - /* We don't support these controls, so we fail for now.*/ - retTemplate = NULL; - break; - default: - retTemplate = NULL; - } - return retTemplate; -} - -static SECStatus -crmf_encode_pkiarchiveoptions(PRArenaPool *poolp, CRMFControl *inControl) -{ - const SEC_ASN1Template *asn1Template; - SECStatus rv; - - asn1Template = crmf_get_pkiarchiveoptions_subtemplate(inControl); - /* We've got a union, so passing a pointer to one element of the - * union, is the same as passing a pointer to any of the other - * members of the union. - */ - SEC_ASN1EncodeItem(poolp, &inControl->derValue, - &inControl->value.archiveOptions, asn1Template); - - if (inControl->derValue.data == NULL) { - goto loser; - } - return SECSuccess; - loser: - return SECFailure; -} - -SECStatus -CRMF_CertRequestSetPKIArchiveOptions(CRMFCertRequest *inCertReq, - CRMFPKIArchiveOptions *inOptions) -{ - CRMFControl *newControl; - PRArenaPool *poolp; - SECStatus rv; - void *mark; - - PORT_Assert(inCertReq != NULL && inOptions != NULL); - if (inCertReq == NULL || inOptions == NULL) { - return SECFailure; - } - poolp = inCertReq->poolp; - mark = PORT_ArenaMark(poolp); - rv = crmf_add_new_control(inCertReq, - SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS, - &newControl); - if (rv != SECSuccess) { - goto loser; - } - - rv = crmf_copy_pkiarchiveoptions(poolp, - &newControl->value.archiveOptions, - inOptions); - if (rv != SECSuccess) { - goto loser; - } - - rv = crmf_encode_pkiarchiveoptions(poolp, newControl); - if (rv != SECSuccess) { - goto loser; - } - PORT_ArenaUnmark(poolp, mark); - return SECSuccess; - loser: - PORT_ArenaRelease(poolp, mark); - return SECFailure; -} - -SECStatus -crmf_destroy_control(CRMFControl *inControl, PRBool freeit) -{ - PORT_Assert(inControl != NULL); - if (inControl != NULL) { - SECITEM_FreeItem(&inControl->derTag, PR_FALSE); - SECITEM_FreeItem(&inControl->derValue, PR_FALSE); - /* None of the other tags require special processing at - * the moment when freeing because they are not supported, - * but if/when they are, add the necessary routines here. - * If all controls are supported, then every member of the - * union inControl->value will have a case that deals with - * it in the following switch statement. - */ - switch (inControl->tag) { - case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS: - crmf_destroy_pkiarchiveoptions(&inControl->value.archiveOptions, - PR_FALSE); - break; - default: - /* Put this here to get rid of all those annoying warnings.*/ - break; - } - if (freeit) { - PORT_Free(inControl); - } - } - return SECSuccess; -} - -SECStatus -CRMF_DestroyControl(CRMFControl *inControl) -{ - return crmf_destroy_control(inControl, PR_TRUE); -} - -static SECOidTag -crmf_controltype_to_tag(CRMFControlType inControlType) -{ - SECOidTag retVal; - - switch(inControlType) { - case crmfRegTokenControl: - retVal = SEC_OID_PKIX_REGCTRL_REGTOKEN; - break; - case crmfAuthenticatorControl: - retVal = SEC_OID_PKIX_REGCTRL_AUTHENTICATOR; - break; - case crmfPKIPublicationInfoControl: - retVal = SEC_OID_PKIX_REGCTRL_PKIPUBINFO; - break; - case crmfPKIArchiveOptionsControl: - retVal = SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS; - break; - case crmfOldCertIDControl: - retVal = SEC_OID_PKIX_REGCTRL_OLD_CERT_ID; - break; - case crmfProtocolEncrKeyControl: - retVal = SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY; - break; - default: - retVal = SEC_OID_UNKNOWN; - break; - } - return retVal; -} - -PRBool -CRMF_CertRequestIsControlPresent(CRMFCertRequest *inCertReq, - CRMFControlType inControlType) -{ - SECOidTag controlTag; - int i; - - PORT_Assert(inCertReq != NULL); - if (inCertReq == NULL || inCertReq->controls == NULL) { - return PR_FALSE; - } - controlTag = crmf_controltype_to_tag(inControlType); - for (i=0; inCertReq->controls[i] != NULL; i++) { - if (inCertReq->controls[i]->tag == controlTag) { - return PR_TRUE; - } - } - return PR_FALSE; -} - |