NSSToken * nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot) { NSSToken *rvToken; NSSArena *arena; /* Don't create a token object for a disabled slot */ if (nss3slot->disabled) { PORT_SetError(SEC_ERROR_NO_TOKEN); return NULL; } arena = nssArena_Create(); if (!arena) { return NULL; } rvToken = nss_ZNEW(arena, NSSToken); if (!rvToken) { nssArena_Destroy(arena); return NULL; } rvToken->base.refCount = 1; rvToken->base.lock = PZ_NewLock(nssILockOther); if (!rvToken->base.lock) { nssArena_Destroy(arena); return NULL; } rvToken->base.arena = arena; rvToken->pk11slot = nss3slot; rvToken->epv = nss3slot->functionList; rvToken->defaultSession = nssSession_ImportNSS3Session(td->arena, nss3slot->session, nss3slot->sessionLock, nss3slot->defRWSession); /* continue, even if rvToken->defaultSession is NULL */ if (!PK11_IsInternal(nss3slot) && PK11_IsHW(nss3slot)) { rvToken->cache = nssTokenObjectCache_Create(rvToken, PR_TRUE, PR_TRUE, PR_TRUE); if (!rvToken->cache) goto loser; } rvToken->trustDomain = td; /* Grab the token name from the PKCS#11 fixed-length buffer */ rvToken->base.name = nssUTF8_Duplicate(nss3slot->token_name,td->arena); rvToken->slot = nssSlot_CreateFromPK11SlotInfo(td, nss3slot); if (!rvToken->slot) { goto loser; } rvToken->slot->token = rvToken; if (rvToken->defaultSession) rvToken->defaultSession->slot = rvToken->slot; return rvToken; loser: PZ_DestroyLock(rvToken->base.lock); nssArena_Destroy(arena); return NULL; }
NS_IMETHODIMP nsPK11Token::IsHardwareToken(bool *_retval) { nsNSSShutDownPreventionLock locker; if (isAlreadyShutDown()) return NS_ERROR_NOT_AVAILABLE; nsresult rv = NS_OK; *_retval = PK11_IsHW(mSlot); return rv; }
static PRBool module_has_removable_hw_slots(SECMODModule *mod) { int i; PRBool ret = PR_FALSE; SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock(); if (!moduleLock) { PORT_SetError(SEC_ERROR_NOT_INITIALIZED); return ret; } SECMOD_GetReadLock(moduleLock); for (i = 0; i < mod->slotCount; i++) { PK11SlotInfo *slot = mod->slots[i]; if (PK11_IsRemovable(slot) && PK11_IsHW(slot)) { ret = PR_TRUE; break; } } SECMOD_ReleaseReadLock(moduleLock); return ret; }
/* * NSS_CMSCipherContext_StartDecrypt - create a cipher context to do decryption * based on the given bulk encryption key and algorithm identifier (which * may include an iv). * * XXX Once both are working, it might be nice to combine this and the * function below (for starting up encryption) into one routine, and just * have two simple cover functions which call it. */ NSSCMSCipherContext * NSS_CMSCipherContext_StartDecrypt(PK11SymKey *key, SECAlgorithmID *algid) { NSSCMSCipherContext *cc; void *ciphercx; CK_MECHANISM_TYPE cryptoMechType; PK11SlotInfo *slot; SECOidTag algtag; SECItem *param = NULL; algtag = SECOID_GetAlgorithmTag(algid); /* set param and mechanism */ if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { SECItem *pwitem; pwitem = PK11_GetSymKeyUserData(key); if (!pwitem) return NULL; cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); if (cryptoMechType == CKM_INVALID_MECHANISM) { SECITEM_FreeItem(param,PR_TRUE); return NULL; } } else { cryptoMechType = PK11_AlgtagToMechanism(algtag); if ((param = PK11_ParamFromAlgid(algid)) == NULL) return NULL; } cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext)); if (cc == NULL) { SECITEM_FreeItem(param,PR_TRUE); return NULL; } /* figure out pad and block sizes */ cc->pad_size = PK11_GetBlockSize(cryptoMechType, param); slot = PK11_GetSlotFromKey(key); cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size; PK11_FreeSlot(slot); /* create PK11 cipher context */ ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT, key, param); SECITEM_FreeItem(param, PR_TRUE); if (ciphercx == NULL) { PORT_Free (cc); return NULL; } cc->cx = ciphercx; cc->doit = (nss_cms_cipher_function) PK11_CipherOp; cc->destroy = (nss_cms_cipher_destroy) PK11_DestroyContext; cc->encrypt = PR_FALSE; cc->pending_count = 0; return cc; }
/* * NSS_CMSCipherContext_StartEncrypt - create a cipher object to do encryption, * based on the given bulk encryption key and algorithm tag. Fill in the * algorithm identifier (which may include an iv) appropriately. * * XXX Once both are working, it might be nice to combine this and the * function above (for starting up decryption) into one routine, and just * have two simple cover functions which call it. */ NSSCMSCipherContext * NSS_CMSCipherContext_StartEncrypt(PLArenaPool *poolp, PK11SymKey *key, SECAlgorithmID *algid) { NSSCMSCipherContext *cc; void *ciphercx; SECStatus rv; CK_MECHANISM_TYPE cryptoMechType; PK11SlotInfo *slot; SECItem *param = NULL; PRBool needToEncodeAlgid = PR_FALSE; SECOidTag algtag = SECOID_GetAlgorithmTag(algid); /* set param and mechanism */ if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { SECItem *pwitem; pwitem = PK11_GetSymKeyUserData(key); if (!pwitem) return NULL; cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); if (cryptoMechType == CKM_INVALID_MECHANISM) { SECITEM_FreeItem(param,PR_TRUE); return NULL; } } else { cryptoMechType = PK11_AlgtagToMechanism(algtag); if ((param = PK11_GenerateNewParam(cryptoMechType, key)) == NULL) return NULL; needToEncodeAlgid = PR_TRUE; } cc = (NSSCMSCipherContext *)PORT_ZAlloc(sizeof(NSSCMSCipherContext)); if (cc == NULL) { goto loser; } /* now find pad and block sizes for our mechanism */ cc->pad_size = PK11_GetBlockSize(cryptoMechType, param); slot = PK11_GetSlotFromKey(key); cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size; PK11_FreeSlot(slot); /* and here we go, creating a PK11 cipher context */ ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT, key, param); if (ciphercx == NULL) { PORT_Free(cc); cc = NULL; goto loser; } /* * These are placed after the CreateContextBySymKey() because some * mechanisms have to generate their IVs from their card (i.e. FORTEZZA). * Don't move it from here. * XXX is that right? the purpose of this is to get the correct algid * containing the IVs etc. for encoding. this means we need to set this up * BEFORE encoding the algid in the contentInfo, right? */ if (needToEncodeAlgid) { rv = PK11_ParamToAlgid(algtag, param, poolp, algid); if(rv != SECSuccess) { PORT_Free(cc); cc = NULL; goto loser; } } cc->cx = ciphercx; cc->doit = (nss_cms_cipher_function)PK11_CipherOp; cc->destroy = (nss_cms_cipher_destroy)PK11_DestroyContext; cc->encrypt = PR_TRUE; cc->pending_count = 0; loser: SECITEM_FreeItem(param, PR_TRUE); return cc; }
/* * Create a cipher object to do decryption, based on the given bulk * encryption key and algorithm identifier (which may include an iv). * * XXX This interface, or one similar, would be really nice available * in general... I tried to keep the pkcs7-specific stuff (mostly * having to do with padding) out of here. * * XXX Once both are working, it might be nice to combine this and the * function below (for starting up encryption) into one routine, and just * have two simple cover functions which call it. */ sec_PKCS7CipherObject * sec_PKCS7CreateDecryptObject (PK11SymKey *key, SECAlgorithmID *algid) { sec_PKCS7CipherObject *result; SECOidTag algtag; void *ciphercx; CK_MECHANISM_TYPE cryptoMechType; PK11SlotInfo *slot; SECItem *param = NULL; result = (struct sec_pkcs7_cipher_object*) PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object)); if (result == NULL) return NULL; ciphercx = NULL; algtag = SECOID_GetAlgorithmTag (algid); if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { SECItem *pwitem; pwitem = (SECItem *)PK11_GetSymKeyUserData(key); if (!pwitem) { PORT_Free(result); return NULL; } cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); if (cryptoMechType == CKM_INVALID_MECHANISM) { PORT_Free(result); SECITEM_FreeItem(param,PR_TRUE); return NULL; } } else { cryptoMechType = PK11_AlgtagToMechanism(algtag); param = PK11_ParamFromAlgid(algid); if (param == NULL) { PORT_Free(result); return NULL; } } result->pad_size = PK11_GetBlockSize(cryptoMechType, param); slot = PK11_GetSlotFromKey(key); result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size; PK11_FreeSlot(slot); ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT, key, param); SECITEM_FreeItem(param,PR_TRUE); if (ciphercx == NULL) { PORT_Free (result); return NULL; } result->cx = ciphercx; result->doit = (sec_pkcs7_cipher_function) PK11_CipherOp; result->destroy = (sec_pkcs7_cipher_destroy) PK11_DestroyContext; result->encrypt = PR_FALSE; result->pending_count = 0; return result; }
/* * Create a cipher object to do encryption, based on the given bulk * encryption key and algorithm tag. Fill in the algorithm identifier * (which may include an iv) appropriately. * * XXX This interface, or one similar, would be really nice available * in general... I tried to keep the pkcs7-specific stuff (mostly * having to do with padding) out of here. * * XXX Once both are working, it might be nice to combine this and the * function above (for starting up decryption) into one routine, and just * have two simple cover functions which call it. */ sec_PKCS7CipherObject * sec_PKCS7CreateEncryptObject (PRArenaPool *poolp, PK11SymKey *key, SECOidTag algtag, SECAlgorithmID *algid) { sec_PKCS7CipherObject *result; void *ciphercx; SECStatus rv; CK_MECHANISM_TYPE cryptoMechType; PK11SlotInfo *slot; SECItem *param = NULL; PRBool needToEncodeAlgid = PR_FALSE; result = (struct sec_pkcs7_cipher_object*) PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object)); if (result == NULL) return NULL; ciphercx = NULL; if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { SECItem *pwitem; pwitem = (SECItem *)PK11_GetSymKeyUserData(key); if (!pwitem) { PORT_Free(result); return NULL; } cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); if (cryptoMechType == CKM_INVALID_MECHANISM) { PORT_Free(result); SECITEM_FreeItem(param,PR_TRUE); return NULL; } } else { cryptoMechType = PK11_AlgtagToMechanism(algtag); param = PK11_GenerateNewParam(cryptoMechType, key); if (param == NULL) { PORT_Free(result); return NULL; } needToEncodeAlgid = PR_TRUE; } result->pad_size = PK11_GetBlockSize(cryptoMechType,param); slot = PK11_GetSlotFromKey(key); result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size; PK11_FreeSlot(slot); ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT, key, param); if (ciphercx == NULL) { PORT_Free (result); SECITEM_FreeItem(param,PR_TRUE); return NULL; } /* * These are placed after the CreateContextBySymKey() because some * mechanisms have to generate their IVs from their card (i.e. FORTEZZA). * Don't move it from here. */ if (needToEncodeAlgid) { rv = PK11_ParamToAlgid(algtag,param,poolp,algid); if(rv != SECSuccess) { PORT_Free (result); SECITEM_FreeItem(param,PR_TRUE); return NULL; } } SECITEM_FreeItem(param,PR_TRUE); result->cx = ciphercx; result->doit = (sec_pkcs7_cipher_function) PK11_CipherOp; result->destroy = (sec_pkcs7_cipher_destroy) PK11_DestroyContext; result->encrypt = PR_TRUE; result->pending_count = 0; return result; }
VCardEmulError vcard_emul_init(const VCardEmulOptions *options) { SECStatus rv; PRBool ret, has_readers = PR_FALSE; VReader *vreader; VReaderEmul *vreader_emul; SECMODListLock *module_lock; SECMODModuleList *module_list; SECMODModuleList *mlp; int i; if (vcard_emul_init_called) { return VCARD_EMUL_INIT_ALREADY_INITED; } vcard_emul_init_called = 1; vreader_init(); vevent_queue_init(); if (options == NULL) { options = &default_options; } /* first initialize NSS */ if (options->nss_db) { rv = NSS_Init(options->nss_db); } else { gchar *path; #ifndef _WIN32 path = g_strdup("/etc/pki/nssdb"); #else if (g_get_system_config_dirs() == NULL || g_get_system_config_dirs()[0] == NULL) { return VCARD_EMUL_FAIL; } path = g_build_filename( g_get_system_config_dirs()[0], "pki", "nssdb", NULL); #endif rv = NSS_Init(path); g_free(path); } if (rv != SECSuccess) { return VCARD_EMUL_FAIL; } /* Set password callback function */ PK11_SetPasswordFunc(vcard_emul_get_password); /* set up soft cards emulated by software certs rather than physical cards * */ for (i = 0; i < options->vreader_count; i++) { int j; int cert_count; unsigned char **certs; int *cert_len; VCardKey **keys; PK11SlotInfo *slot; slot = PK11_FindSlotByName(options->vreader[i].name); if (slot == NULL) { continue; } vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type, options->vreader[i].type_params); vreader = vreader_new(options->vreader[i].vname, vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); cert_count = options->vreader[i].cert_count; ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, options->vreader[i].cert_count); if (ret == PR_FALSE) { continue; } cert_count = 0; for (j = 0; j < options->vreader[i].cert_count; j++) { /* we should have a better way of identifying certs than by * nickname here */ CERTCertificate *cert = PK11_FindCertFromNickname( options->vreader[i].cert_name[j], NULL); if (cert == NULL) { continue; } certs[cert_count] = cert->derCert.data; cert_len[cert_count] = cert->derCert.len; keys[cert_count] = vcard_emul_make_key(slot, cert); /* this is safe because the key is still holding a cert reference */ CERT_DestroyCertificate(cert); cert_count++; } if (cert_count) { VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); /* allow insertion and removal of soft cards */ vreader_emul->saved_vcard = vcard_reference(vcard); vcard_free(vcard); vreader_free(vreader); has_readers = PR_TRUE; } g_free(certs); g_free(cert_len); g_free(keys); } /* if we aren't suppose to use hw, skip looking up hardware tokens */ if (!options->use_hw) { nss_emul_init = has_readers; return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL; } /* make sure we have some PKCS #11 module loaded */ module_lock = SECMOD_GetDefaultModuleListLock(); module_list = SECMOD_GetDefaultModuleList(); SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; if (module_has_removable_hw_slots(module)) { break; } } SECMOD_ReleaseReadLock(module_lock); /* now examine all the slots, finding which should be readers */ /* We should control this with options. For now we mirror out any * removable hardware slot */ default_card_type = options->hw_card_type; default_type_params = g_strdup(options->hw_type_params); SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; /* Ignore the internal module */ if (module == NULL || module == SECMOD_GetInternalModule()) { continue; } for (i = 0; i < module->slotCount; i++) { PK11SlotInfo *slot = module->slots[i]; /* only map removable HW slots */ if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) { continue; } if (strcmp("E-Gate 0 0", PK11_GetSlotName(slot)) == 0) { /* * coolkey <= 1.1.0-20 emulates this reader if it can't find * any hardware readers. This causes problems, warn user of * problems. */ fprintf(stderr, "known bad coolkey version - see " "https://bugzilla.redhat.com/show_bug.cgi?id=802435\n"); continue; } vreader_emul = vreader_emul_new(slot, options->hw_card_type, options->hw_type_params); vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); if (PK11_IsPresent(slot)) { VCard *vcard; vcard = vcard_emul_mirror_card(vreader); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); vcard_free(vcard); } } vcard_emul_new_event_thread(module); } SECMOD_ReleaseReadLock(module_lock); nss_emul_init = PR_TRUE; return VCARD_EMUL_OK; }
VCardEmulError vcard_emul_init(const VCardEmulOptions *options) { SECStatus rv; PRBool ret, has_readers = PR_FALSE, need_coolkey_module; VReader *vreader; VReaderEmul *vreader_emul; SECMODListLock *module_lock; SECMODModuleList *module_list; SECMODModuleList *mlp; int i; if (vcard_emul_init_called) { return VCARD_EMUL_INIT_ALREADY_INITED; } vcard_emul_init_called = 1; vreader_init(); vevent_queue_init(); if (options == NULL) { options = &default_options; } /* first initialize NSS */ if (options->nss_db) { rv = NSS_Init(options->nss_db); } else { rv = NSS_Init("sql:/etc/pki/nssdb"); } if (rv != SECSuccess) { return VCARD_EMUL_FAIL; } /* Set password callback function */ PK11_SetPasswordFunc(vcard_emul_get_password); /* set up soft cards emulated by software certs rather than physical cards * */ for (i = 0; i < options->vreader_count; i++) { int j; int cert_count; unsigned char **certs; int *cert_len; VCardKey **keys; PK11SlotInfo *slot; slot = PK11_FindSlotByName(options->vreader[i].name); if (slot == NULL) { continue; } vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type, options->vreader[i].type_params); vreader = vreader_new(options->vreader[i].vname, vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); cert_count = options->vreader[i].cert_count; ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, options->vreader[i].cert_count); if (ret == PR_FALSE) { continue; } cert_count = 0; for (j = 0; j < options->vreader[i].cert_count; j++) { /* we should have a better way of identifying certs than by * nickname here */ CERTCertificate *cert = PK11_FindCertFromNickname( options->vreader[i].cert_name[j], NULL); if (cert == NULL) { continue; } certs[cert_count] = cert->derCert.data; cert_len[cert_count] = cert->derCert.len; keys[cert_count] = vcard_emul_make_key(slot, cert); /* this is safe because the key is still holding a cert reference */ CERT_DestroyCertificate(cert); cert_count++; } if (cert_count) { VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); /* allow insertion and removal of soft cards */ vreader_emul->saved_vcard = vcard_reference(vcard); vcard_free(vcard); vreader_free(vreader); has_readers = PR_TRUE; } g_free(certs); g_free(cert_len); g_free(keys); } /* if we aren't suppose to use hw, skip looking up hardware tokens */ if (!options->use_hw) { nss_emul_init = has_readers; return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL; } /* make sure we have some PKCS #11 module loaded */ module_lock = SECMOD_GetDefaultModuleListLock(); module_list = SECMOD_GetDefaultModuleList(); need_coolkey_module = !has_readers; SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; if (module_has_removable_hw_slots(module)) { need_coolkey_module = PR_FALSE; break; } } SECMOD_ReleaseReadLock(module_lock); if (need_coolkey_module) { SECMODModule *module; module = SECMOD_LoadUserModule( (char *)"library=libcoolkeypk11.so name=Coolkey", NULL, PR_FALSE); if (module == NULL) { return VCARD_EMUL_FAIL; } SECMOD_DestroyModule(module); /* free our reference, Module will still * be on the list. * until we destroy it */ } /* now examine all the slots, finding which should be readers */ /* We should control this with options. For now we mirror out any * removable hardware slot */ default_card_type = options->hw_card_type; default_type_params = strdup(options->hw_type_params); SECMOD_GetReadLock(module_lock); for (mlp = module_list; mlp; mlp = mlp->next) { SECMODModule *module = mlp->module; PRBool has_emul_slots = PR_FALSE; if (module == NULL) { continue; } for (i = 0; i < module->slotCount; i++) { PK11SlotInfo *slot = module->slots[i]; /* only map removable HW slots */ if (slot == NULL || !PK11_IsRemovable(slot) || !PK11_IsHW(slot)) { continue; } vreader_emul = vreader_emul_new(slot, options->hw_card_type, options->hw_type_params); vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul, vreader_emul_delete); vreader_add_reader(vreader); has_readers = PR_TRUE; has_emul_slots = PR_TRUE; if (PK11_IsPresent(slot)) { VCard *vcard; vcard = vcard_emul_mirror_card(vreader); vreader_insert_card(vreader, vcard); vcard_emul_init_series(vreader, vcard); vcard_free(vcard); } } if (has_emul_slots) { vcard_emul_new_event_thread(module); } } SECMOD_ReleaseReadLock(module_lock); nss_emul_init = has_readers; return VCARD_EMUL_OK; }
/* * SecCmsCipherContextStartEncrypt - create a cipher object to do encryption, * based on the given bulk encryption key and algorithm tag. Fill in the algorithm * identifier (which may include an iv) appropriately. * * XXX Once both are working, it might be nice to combine this and the * function above (for starting up decryption) into one routine, and just * have two simple cover functions which call it. */ SecCmsCipherContext * SecCmsCipherContextStartEncrypt(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid) { return SecCmsCipherContextStart(poolp, key, algid, PR_TRUE); #if 0 SecCmsCipherContext *cc; void *ciphercx; CSSM_DATA *param; OSStatus rv; CK_MECHANISM_TYPE mechanism; PK11SlotInfo *slot; PRBool needToEncodeAlgid = PR_FALSE; SECOidTag algtag = SECOID_GetAlgorithmTag(algid); /* set param and mechanism */ if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { CK_MECHANISM pbeMech, cryptoMech; CSSM_DATA *pbeParams; SEC_PKCS5KeyAndPassword *keyPwd; PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM)); PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM)); /* HACK ALERT! * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword * */ keyPwd = (SEC_PKCS5KeyAndPassword *)key; key = keyPwd->key; /* find correct PK11 mechanism and parameters to initialize pbeMech */ pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); pbeParams = PK11_ParamFromAlgid(algid); if (!pbeParams) return NULL; pbeMech.pParameter = pbeParams->Data; pbeMech.ulParameterLen = pbeParams->Length; /* now map pbeMech to cryptoMech */ if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem, PR_FALSE) != CKR_OK) { SECITEM_ZfreeItem(pbeParams, PR_TRUE); return NULL; } SECITEM_ZfreeItem(pbeParams, PR_TRUE); /* and use it to initialize param & mechanism */ if ((param = (CSSM_DATA *)PORT_ZAlloc(sizeof(CSSM_DATA))) == NULL) return NULL; param->Data = (unsigned char *)cryptoMech.pParameter; param->Length = cryptoMech.ulParameterLen; mechanism = cryptoMech.mechanism; } else { mechanism = PK11_AlgtagToMechanism(algtag); if ((param = PK11_GenerateNewParam(mechanism, key)) == NULL) return NULL; needToEncodeAlgid = PR_TRUE; } cc = (SecCmsCipherContext *)PORT_ZAlloc(sizeof(SecCmsCipherContext)); if (cc == NULL) return NULL; /* now find pad and block sizes for our mechanism */ cc->pad_size = PK11_GetBlockSize(mechanism,param); slot = PK11_GetSlotFromKey(key); cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size; PK11_FreeSlot(slot); /* and here we go, creating a PK11 cipher context */ ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_ENCRYPT, key, param); if (ciphercx == NULL) { PORT_Free(cc); cc = NULL; goto loser; } /* * These are placed after the CreateContextBySymKey() because some * mechanisms have to generate their IVs from their card (i.e. FORTEZZA). * Don't move it from here. * XXX is that right? the purpose of this is to get the correct algid * containing the IVs etc. for encoding. this means we need to set this up * BEFORE encoding the algid in the contentInfo, right? */ if (needToEncodeAlgid) { rv = PK11_ParamToAlgid(algtag, param, poolp, algid); if(rv != SECSuccess) { PORT_Free(cc); cc = NULL; goto loser; } } cc->cx = ciphercx; cc->doit = (nss_cms_cipher_function)PK11_CipherOp; cc->destroy = (nss_cms_cipher_destroy)PK11_DestroyContext; cc->encrypt = PR_TRUE; cc->pending_count = 0; loser: SECITEM_FreeItem(param, PR_TRUE); return cc; #endif }
/* * SecCmsCipherContextStartDecrypt - create a cipher context to do decryption * based on the given bulk * encryption key and algorithm identifier (which may include an iv). * * XXX Once both are working, it might be nice to combine this and the * function below (for starting up encryption) into one routine, and just * have two simple cover functions which call it. */ SecCmsCipherContext * SecCmsCipherContextStartDecrypt(SecSymmetricKeyRef key, SECAlgorithmID *algid) { return SecCmsCipherContextStart(NULL, key, algid, PR_FALSE); #if 0 SecCmsCipherContext *cc; void *ciphercx; CK_MECHANISM_TYPE mechanism; CSSM_DATA *param; PK11SlotInfo *slot; SECOidTag algtag; algtag = SECOID_GetAlgorithmTag(algid); /* set param and mechanism */ if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { CK_MECHANISM pbeMech, cryptoMech; CSSM_DATA *pbeParams; SEC_PKCS5KeyAndPassword *keyPwd; PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM)); PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM)); /* HACK ALERT! * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword * */ keyPwd = (SEC_PKCS5KeyAndPassword *)key; key = keyPwd->key; /* find correct PK11 mechanism and parameters to initialize pbeMech */ pbeMech.mechanism = PK11_AlgtagToMechanism(algtag); pbeParams = PK11_ParamFromAlgid(algid); if (!pbeParams) return NULL; pbeMech.pParameter = pbeParams->Data; pbeMech.ulParameterLen = pbeParams->Length; /* now map pbeMech to cryptoMech */ if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem, PR_FALSE) != CKR_OK) { SECITEM_ZfreeItem(pbeParams, PR_TRUE); return NULL; } SECITEM_ZfreeItem(pbeParams, PR_TRUE); /* and use it to initialize param & mechanism */ if ((param = (CSSM_DATA *)PORT_ZAlloc(sizeof(CSSM_DATA))) == NULL) return NULL; param->Data = (unsigned char *)cryptoMech.pParameter; param->Length = cryptoMech.ulParameterLen; mechanism = cryptoMech.mechanism; } else { mechanism = PK11_AlgtagToMechanism(algtag); if ((param = PK11_ParamFromAlgid(algid)) == NULL) return NULL; } cc = (SecCmsCipherContext *)PORT_ZAlloc(sizeof(SecCmsCipherContext)); if (cc == NULL) { SECITEM_FreeItem(param,PR_TRUE); return NULL; } /* figure out pad and block sizes */ cc->pad_size = PK11_GetBlockSize(mechanism, param); slot = PK11_GetSlotFromKey(key); cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size; PK11_FreeSlot(slot); /* create PK11 cipher context */ ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_DECRYPT, key, param); SECITEM_FreeItem(param, PR_TRUE); if (ciphercx == NULL) { PORT_Free (cc); return NULL; } cc->cx = ciphercx; cc->doit = (nss_cms_cipher_function) PK11_CipherOp; cc->destroy = (nss_cms_cipher_destroy) PK11_DestroyContext; cc->encrypt = PR_FALSE; cc->pending_count = 0; return cc; #endif }
/*********************************************************************** * * L i s t M o d u l e * * Lists detailed information about the named module. */ Error ListModule(char *moduleName) { SECMODModule *module = NULL; PK11SlotInfo *slot; int slotnum; CK_INFO modinfo; CK_SLOT_INFO slotinfo; CK_TOKEN_INFO tokeninfo; char *ciphers, *mechanisms; size_t reasonIdx; Error rv = SUCCESS; if (!moduleName) { return SUCCESS; } module = SECMOD_FindModule(moduleName); if (!module) { PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName); rv = NO_SUCH_MODULE_ERR; goto loser; } if ((module->loaded) && (PK11_GetModInfo(module, &modinfo) != SECSuccess)) { PR_fprintf(PR_STDERR, errStrings[MOD_INFO_ERR], moduleName); rv = MOD_INFO_ERR; goto loser; } /* Module info */ PR_fprintf(PR_STDOUT, "\n-----------------------------------------------------------\n"); PR_fprintf(PR_STDOUT, "Name: %s\n", module->commonName); if (module->internal || !module->dllName) { PR_fprintf(PR_STDOUT, "Library file: **Internal ONLY module**\n"); } else { PR_fprintf(PR_STDOUT, "Library file: %s\n", module->dllName); } if (module->loaded) { PR_fprintf(PR_STDOUT, "Manufacturer: %.32s\n", modinfo.manufacturerID); PR_fprintf(PR_STDOUT, "Description: %.32s\n", modinfo.libraryDescription); PR_fprintf(PR_STDOUT, "PKCS #11 Version %d.%d\n", modinfo.cryptokiVersion.major, modinfo.cryptokiVersion.minor); PR_fprintf(PR_STDOUT, "Library Version: %d.%d\n", modinfo.libraryVersion.major, modinfo.libraryVersion.minor); } else { PR_fprintf(PR_STDOUT, "* Module not loaded\n"); } /* Get cipher and mechanism flags */ ciphers = getStringFromFlags(module->ssl[0], cipherStrings, numCipherStrings); if (ciphers[0] == '\0') { ciphers = "None"; } PR_fprintf(PR_STDOUT, "Cipher Enable Flags: %s\n", ciphers); mechanisms = NULL; if (module->slotCount > 0) { mechanisms = getStringFromFlags( PK11_GetDefaultFlags(module->slots[0]), mechanismStrings, numMechanismStrings); } if ((mechanisms == NULL) || (mechanisms[0] == '\0')) { mechanisms = "None"; } PR_fprintf(PR_STDOUT, "Default Mechanism Flags: %s\n", mechanisms); #define PAD " " /* Loop over each slot */ for (slotnum = 0; slotnum < module->slotCount; slotnum++) { slot = module->slots[slotnum]; if (PK11_GetSlotInfo(slot, &slotinfo) != SECSuccess) { PR_fprintf(PR_STDERR, errStrings[SLOT_INFO_ERR], PK11_GetSlotName(slot)); rv = SLOT_INFO_ERR; continue; } /* Slot Info */ PR_fprintf(PR_STDOUT, "\n" PAD "Slot: %s\n", PK11_GetSlotName(slot)); mechanisms = getStringFromFlags(PK11_GetDefaultFlags(slot), mechanismStrings, numMechanismStrings); if (mechanisms[0] == '\0') { mechanisms = "None"; } PR_fprintf(PR_STDOUT, PAD "Slot Mechanism Flags: %s\n", mechanisms); PR_fprintf(PR_STDOUT, PAD "Manufacturer: %.32s\n", slotinfo.manufacturerID); if (PK11_IsHW(slot)) { PR_fprintf(PR_STDOUT, PAD "Type: Hardware\n"); } else { PR_fprintf(PR_STDOUT, PAD "Type: Software\n"); } PR_fprintf(PR_STDOUT, PAD "Version Number: %d.%d\n", slotinfo.hardwareVersion.major, slotinfo.hardwareVersion.minor); PR_fprintf(PR_STDOUT, PAD "Firmware Version: %d.%d\n", slotinfo.firmwareVersion.major, slotinfo.firmwareVersion.minor); if (PK11_IsDisabled(slot)) { reasonIdx = PK11_GetDisabledReason(slot); if (reasonIdx < numDisableReasonStr) { PR_fprintf(PR_STDOUT, PAD "Status: DISABLED (%s)\n", disableReasonStr[reasonIdx]); } else { PR_fprintf(PR_STDOUT, PAD "Status: DISABLED\n"); } } else { PR_fprintf(PR_STDOUT, PAD "Status: Enabled\n"); } if (PK11_GetTokenInfo(slot, &tokeninfo) != SECSuccess) { PR_fprintf(PR_STDERR, errStrings[TOKEN_INFO_ERR], PK11_GetTokenName(slot)); rv = TOKEN_INFO_ERR; continue; } /* Token Info */ PR_fprintf(PR_STDOUT, PAD "Token Name: %.32s\n", tokeninfo.label); PR_fprintf(PR_STDOUT, PAD "Token Manufacturer: %.32s\n", tokeninfo.manufacturerID); PR_fprintf(PR_STDOUT, PAD "Token Model: %.16s\n", tokeninfo.model); PR_fprintf(PR_STDOUT, PAD "Token Serial Number: %.16s\n", tokeninfo.serialNumber); PR_fprintf(PR_STDOUT, PAD "Token Version: %d.%d\n", tokeninfo.hardwareVersion.major, tokeninfo.hardwareVersion.minor); PR_fprintf(PR_STDOUT, PAD "Token Firmware Version: %d.%d\n", tokeninfo.firmwareVersion.major, tokeninfo.firmwareVersion.minor); if (tokeninfo.flags & CKF_WRITE_PROTECTED) { PR_fprintf(PR_STDOUT, PAD "Access: Write Protected\n"); } else { PR_fprintf(PR_STDOUT, PAD "Access: NOT Write Protected\n"); } if (tokeninfo.flags & CKF_LOGIN_REQUIRED) { PR_fprintf(PR_STDOUT, PAD "Login Type: Login required\n"); } else { PR_fprintf(PR_STDOUT, PAD "Login Type: Public (no login required)\n"); } if (tokeninfo.flags & CKF_USER_PIN_INITIALIZED) { PR_fprintf(PR_STDOUT, PAD "User Pin: Initialized\n"); } else { PR_fprintf(PR_STDOUT, PAD "User Pin: NOT Initialized\n"); } } PR_fprintf(PR_STDOUT, "\n-----------------------------------------------------------\n"); loser: if (module) { SECMOD_DestroyModule(module); } return rv; }