/* * Digest contexts don't need keys, but the do need to find a slot. * Macing should use PK11_CreateContextBySymKey. */ PK11Context * PK11_CreateDigestContext(SECOidTag hashAlg) { /* digesting has to work without authentication to the slot */ CK_MECHANISM_TYPE type; PK11SlotInfo *slot; PK11Context *context; SECItem param; type = PK11_AlgtagToMechanism(hashAlg); slot = PK11_GetBestSlot(type, NULL); if (slot == NULL) { PORT_SetError( SEC_ERROR_NO_MODULE ); return NULL; } /* maybe should really be PK11_GenerateNewParam?? */ param.data = NULL; param.len = 0; param.type = 0; context = pk11_CreateNewContextInSlot(type, slot, CKA_DIGEST, NULL, ¶m); PK11_FreeSlot(slot); return context; }
static int nss_ctx_init(TALLOC_CTX *mem_ctx, struct crypto_mech_data *mech_props, struct sss_nss_crypto_ctx **_cctx) { struct sss_nss_crypto_ctx *cctx; int ret; cctx = talloc_zero(mem_ctx, struct sss_nss_crypto_ctx); if (!cctx) { return ENOMEM; } talloc_set_destructor(cctx, sss_nss_crypto_ctx_destructor); cctx->slot = PK11_GetBestSlot(mech_props->cipher, NULL); if (cctx->slot == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to find security device (err %d)\n", PR_GetError()); ret = EIO; goto done; } ret = EOK; *_cctx = cctx; done: if (ret) talloc_zfree(cctx); return ret; }
static int init_nss_crypto(knet_handle_t knet_h) { PK11SlotInfo* crypt_slot = NULL; SECItem crypt_param; struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; if (!cipher_to_nss[instance->crypto_cipher_type]) { return 0; } crypt_param.type = siBuffer; crypt_param.data = instance->private_key; crypt_param.len = cipher_key_len[instance->crypto_cipher_type]; crypt_slot = PK11_GetBestSlot(cipher_to_nss[instance->crypto_cipher_type], NULL); if (crypt_slot == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to find security slot (err %d)", PR_GetError()); return -1; } instance->nss_sym_key = PK11_ImportSymKey(crypt_slot, cipher_to_nss[instance->crypto_cipher_type], PK11_OriginUnwrap, CKA_ENCRYPT|CKA_DECRYPT, &crypt_param, NULL); if (instance->nss_sym_key == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to import key into NSS (err %d)", PR_GetError()); return -1; } PK11_FreeSlot(crypt_slot); return 0; }
static PK11Context* sipe_crypt_ctx_create(CK_MECHANISM_TYPE cipherMech, const guchar *key, gsize key_length) { PK11SlotInfo* slot; SECItem keyItem; SECItem ivItem; PK11SymKey* SymKey; SECItem *SecParam; PK11Context* EncContext; /* For key */ slot = PK11_GetBestSlot(cipherMech, NULL); keyItem.type = siBuffer; keyItem.data = (unsigned char *)key; keyItem.len = key_length; SymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL); /* Parameter for crypto context */ ivItem.type = siBuffer; ivItem.data = NULL; ivItem.len = 0; SecParam = PK11_ParamFromIV(cipherMech, &ivItem); EncContext = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT, SymKey, SecParam); PK11_FreeSymKey(SymKey); SECITEM_FreeItem(SecParam, PR_TRUE); PK11_FreeSlot(slot); return EncContext; }
static int init_nss_hash(knet_handle_t knet_h) { PK11SlotInfo* hash_slot = NULL; SECItem hash_param; struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; if (!hash_to_nss[instance->crypto_hash_type]) { return 0; } hash_param.type = siBuffer; hash_param.data = instance->private_key; hash_param.len = instance->private_key_len; hash_slot = PK11_GetBestSlot(hash_to_nss[instance->crypto_hash_type], NULL); if (hash_slot == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Unable to find security slot (err %d)", PR_GetError()); return -1; } instance->nss_sym_key_sign = PK11_ImportSymKey(hash_slot, hash_to_nss[instance->crypto_hash_type], PK11_OriginUnwrap, CKA_SIGN, &hash_param, NULL); if (instance->nss_sym_key_sign == NULL) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to import key into NSS (err %d)", PR_GetError()); return -1; } PK11_FreeSlot(hash_slot); return 0; }
/* * put together the various PK11_Create_Context calls used by different * parts of libsec. */ PK11Context * __PK11_CreateContextByRawKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key, SECItem *param, void *wincx) { PK11SymKey *symKey = NULL; PK11Context *context = NULL; /* first get a slot */ if (slot == NULL) { slot = PK11_GetBestSlot(type,wincx); if (slot == NULL) { PORT_SetError( SEC_ERROR_NO_MODULE ); goto loser; } } else { PK11_ReferenceSlot(slot); } /* now import the key */ symKey = PK11_ImportSymKey(slot, type, origin, operation, key, wincx); if (symKey == NULL) goto loser; context = PK11_CreateContextBySymKey(type, operation, symKey, param); loser: if (symKey) { PK11_FreeSymKey(symKey); } if (slot) { PK11_FreeSlot(slot); } return context; }
NS_IMETHODIMP nsKeyObjectFactory::KeyFromString(PRInt16 aAlgorithm, const nsACString & aKey, nsIKeyObject **_retval) { CK_MECHANISM_TYPE cipherMech; CK_ATTRIBUTE_TYPE cipherOperation; switch (aAlgorithm) { case nsIKeyObject::HMAC: cipherMech = CKM_GENERIC_SECRET_KEY_GEN; cipherOperation = CKA_SIGN; break; case nsIKeyObject::RC4: cipherMech = CKM_RC4; cipherOperation = CKA_ENCRYPT; break; default: return NS_ERROR_INVALID_ARG; } nsresult rv; nsCOMPtr<nsIKeyObject> key = do_CreateInstance(NS_KEYMODULEOBJECT_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); // Convert the raw string into a SECItem const nsCString& flatKey = PromiseFlatCString(aKey); SECItem keyItem; keyItem.data = (unsigned char*)flatKey.get(); keyItem.len = flatKey.Length(); PK11SlotInfo *slot = nullptr; slot = PK11_GetBestSlot(cipherMech, nullptr); if (!slot) { NS_ERROR("no slot"); return NS_ERROR_FAILURE; } PK11SymKey* symKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, cipherOperation, &keyItem, nullptr); // cleanup code if (slot) PK11_FreeSlot(slot); if (!symKey) { return NS_ERROR_FAILURE; } rv = key->InitKey(aAlgorithm, (void*)symKey); NS_ENSURE_SUCCESS(rv, rv); key.swap(*_retval); return NS_OK; }
/* * This code is mostly cargo-cult taken from here: * http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn5.html * * It should implement HMAC with the given mechanism (SHA: 1, 256, 384, 512). */ static bool hmac(SECItem *key, CK_MECHANISM_TYPE mech, const SECItem *in, struct digest_buffer *out) { SECItem param = { siBuffer, NULL, 0 }; PK11SlotInfo *slot = NULL; PK11SymKey *symkey = NULL; PK11Context *ctx = NULL; bool ret = false; SECStatus s; slot = PK11_GetBestSlot(mech, NULL); if (slot == NULL) { slot = PK11_GetInternalKeySlot(); if (slot == NULL) { goto done; } } symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_SIGN, key, NULL); if (symkey == NULL) goto done; ctx = PK11_CreateContextBySymKey(mech, CKA_SIGN, symkey, ¶m); if (ctx == NULL) goto done; s = PK11_DigestBegin(ctx); if (s != SECSuccess) goto done; s = PK11_DigestOp(ctx, in->data, in->len); if (s != SECSuccess) goto done; s = PK11_DigestFinal(ctx, out->buf, &out->len, sizeof(out->buf)); if (s != SECSuccess) goto done; ret = true; done: if (ctx != NULL) PK11_DestroyContext(ctx, PR_TRUE); if (symkey != NULL) PK11_FreeSymKey(symkey); if (slot != NULL) PK11_FreeSlot(slot); return ret; }
/* Ask: is ANY ECC cipher suite enabled on this socket? */ static PRBool ssl_IsECCEnabled(sslSocket *ss) { PK11SlotInfo *slot; /* make sure we can do ECC */ slot = PK11_GetBestSlot(CKM_ECDH1_DERIVE, ss->pkcs11PinArg); if (!slot) { return PR_FALSE; } PK11_FreeSlot(slot); /* make sure an ECC cipher is enabled */ return ssl_IsSuiteEnabled(ss, ssl_all_ec_suites); }
static PK11SymKey * xmlSecNssMakeAesKey(const xmlSecByte *key, xmlSecSize keySize, int enc) { CK_MECHANISM_TYPE cipherMech; PK11SlotInfo* slot = NULL; PK11SymKey* aeskey = NULL; SECItem keyItem; xmlSecAssert2(key != NULL, NULL); xmlSecAssert2(keySize > 0, NULL); cipherMech = CKM_AES_ECB; slot = PK11_GetBestSlot(cipherMech, NULL); if (slot == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_GetBestSlot", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } keyItem.data = (unsigned char *)key; keyItem.len = keySize; aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL); if (aeskey == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_ImportSymKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } done: if (slot) { PK11_FreeSlot(slot); } return(aeskey); }
/* This function adopts pubKey and destroys it if things go wrong. */ static sslKeyPair * ssl_MakeKeyPairForCert(SECKEYPrivateKey *key, SECKEYPublicKey *pubKey) { sslKeyPair *keyPair = NULL; SECKEYPrivateKey *privKeyCopy = NULL; PK11SlotInfo *bestSlot; if (key->pkcs11Slot) { bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); if (bestSlot) { privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (!privKeyCopy) { CK_MECHANISM_TYPE keyMech = PK11_MapSignKeyType(key->keyType); /* XXX Maybe should be bestSlotMultiple? */ bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */); if (bestSlot) { privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (!privKeyCopy) { privKeyCopy = SECKEY_CopyPrivateKey(key); } if (privKeyCopy) { keyPair = ssl_NewKeyPair(privKeyCopy, pubKey); } if (!keyPair) { if (privKeyCopy) { SECKEY_DestroyPrivateKey(privKeyCopy); } /* We adopted the public key, so we're responsible. */ if (pubKey) { SECKEY_DestroyPublicKey(pubKey); } } return keyPair; }
SECStatus SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert, const CERTCertificateList *certChainOpt, SECKEYPrivateKey *key, SSL3KEAType kea) { sslSocket *ss; SECKEYPublicKey *pubKey = NULL; ssl3KeyPair *keyPair = NULL; SECStatus rv = SECFailure; ss = ssl_FindSocket(fd); if (!ss) { return SECFailure; } /* Both key and cert must have a value or be NULL */ /* Passing a value of NULL will turn off key exchange algorithms that were * previously turned on */ if (!cert != !key) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } /* make sure the key exchange is recognized */ if ((kea >= kt_kea_size) || (kea < kt_null)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); return SECFailure; } if (kea != NSS_FindCertKEAType(cert)) { PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH); return SECFailure; } if (cert) { /* get the size of the cert's public key, and remember it */ pubKey = CERT_ExtractPublicKey(cert); if (!pubKey) return SECFailure; } if (key) { SECKEYPrivateKey * keyCopy = NULL; CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM; if (key->pkcs11Slot) { PK11SlotInfo * bestSlot; bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyMech = PK11_MapSignKeyType(key->keyType); if (keyMech != CKM_INVALID_MECHANISM) { PK11SlotInfo * bestSlot; /* XXX Maybe should be bestSlotMultiple? */ bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyCopy = SECKEY_CopyPrivateKey(key); if (keyCopy == NULL) goto loser; keyPair = ssl3_NewKeyPair(keyCopy, pubKey); if (keyPair == NULL) { SECKEY_DestroyPrivateKey(keyCopy); goto loser; } pubKey = NULL; /* adopted by serverKeyPair */ } if (ssl_ConfigSecureServer(ss, cert, certChainOpt, keyPair, kea) == SECFailure) { goto loser; } /* Only do this once because it's global. */ if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce, &serverCAListSetup, (void *)(ss->dbHandle))) { rv = SECSuccess; } loser: if (keyPair) { ssl3_FreeKeyPair(keyPair); } if (pubKey) { SECKEY_DestroyPublicKey(pubKey); pubKey = NULL; } return rv; }
static int sm_encrypt(CamelCipherContext *context, const char *userid, GPtrArray *recipients, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex) { struct _CamelSMIMEContextPrivate *p = ((CamelSMIMEContext *)context)->priv; /*NSSCMSRecipientInfo **recipient_infos;*/ CERTCertificate **recipient_certs = NULL; NSSCMSContentInfo *cinfo; PK11SymKey *bulkkey = NULL; SECOidTag bulkalgtag; int bulkkeysize, i; CK_MECHANISM_TYPE type; PK11SlotInfo *slot; PLArenaPool *poolp; NSSCMSMessage *cmsg = NULL; NSSCMSEnvelopedData *envd; NSSCMSEncoderContext *enc = NULL; CamelStreamMem *mem; CamelStream *ostream = NULL; CamelDataWrapper *dw; CamelContentType *ct; poolp = PORT_NewArena(1024); if (poolp == NULL) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, g_strerror (ENOMEM)); return -1; } /* Lookup all recipients certs, for later working */ recipient_certs = (CERTCertificate **)PORT_ArenaZAlloc(poolp, sizeof(*recipient_certs[0])*(recipients->len + 1)); if (recipient_certs == NULL) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, g_strerror (ENOMEM)); goto fail; } for (i=0;i<recipients->len;i++) { recipient_certs[i] = CERT_FindCertByNicknameOrEmailAddr(p->certdb, recipients->pdata[i]); if (recipient_certs[i] == NULL) { camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot find certificate for `%s'"), recipients->pdata[i]); goto fail; } } /* Find a common algorithm, probably 3DES anyway ... */ if (NSS_SMIMEUtil_FindBulkAlgForRecipients(recipient_certs, &bulkalgtag, &bulkkeysize) != SECSuccess) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot find common bulk encryption algorithm")); goto fail; } /* Generate a new bulk key based on the common algorithm - expensive */ type = PK11_AlgtagToMechanism(bulkalgtag); slot = PK11_GetBestSlot(type, context); if (slot == NULL) { /* PORT_GetError(); ?? */ camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot allocate slot for encryption bulk key")); goto fail; } bulkkey = PK11_KeyGen(slot, type, NULL, bulkkeysize/8, context); PK11_FreeSlot(slot); /* Now we can start building the message */ /* msg->envelopedData->data */ cmsg = NSS_CMSMessage_Create(NULL); if (cmsg == NULL) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Message")); goto fail; } envd = NSS_CMSEnvelopedData_Create(cmsg, bulkalgtag, bulkkeysize); if (envd == NULL) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Enveloped data")); goto fail; } cinfo = NSS_CMSMessage_GetContentInfo(cmsg); if (NSS_CMSContentInfo_SetContent_EnvelopedData(cmsg, cinfo, envd) != SECSuccess) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS Enveloped data")); goto fail; } cinfo = NSS_CMSEnvelopedData_GetContentInfo(envd); if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE) != SECSuccess) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS data object")); goto fail; } /* add recipient certs */ for (i=0;recipient_certs[i];i++) { NSSCMSRecipientInfo *ri = NSS_CMSRecipientInfo_Create(cmsg, recipient_certs[i]); if (ri == NULL) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Recipient information")); goto fail; } if (NSS_CMSEnvelopedData_AddRecipient(envd, ri) != SECSuccess) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot add CMS Recipient information")); goto fail; } } /* dump it out */ ostream = camel_stream_mem_new(); enc = NSS_CMSEncoder_Start(cmsg, sm_write_stream, ostream, NULL, NULL, NULL, NULL, sm_decrypt_key, bulkkey, NULL, NULL); if (enc == NULL) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create encoder context")); goto fail; } /* FIXME: Stream the input */ /* FIXME: Canonicalise the input? */ mem = (CamelStreamMem *)camel_stream_mem_new(); camel_data_wrapper_write_to_stream((CamelDataWrapper *)ipart, (CamelStream *)mem); if (NSS_CMSEncoder_Update(enc, (char *) mem->buffer->data, mem->buffer->len) != SECSuccess) { NSS_CMSEncoder_Cancel(enc); camel_object_unref(mem); camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to add data to encoder")); goto fail; } camel_object_unref(mem); if (NSS_CMSEncoder_Finish(enc) != SECSuccess) { camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to encode data")); goto fail; } PK11_FreeSymKey(bulkkey); NSS_CMSMessage_Destroy(cmsg); for (i=0;recipient_certs[i];i++) CERT_DestroyCertificate(recipient_certs[i]); PORT_FreeArena(poolp, PR_FALSE); dw = camel_data_wrapper_new(); camel_data_wrapper_construct_from_stream(dw, ostream); camel_object_unref(ostream); dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY; ct = camel_content_type_new("application", "x-pkcs7-mime"); camel_content_type_set_param(ct, "name", "smime.p7m"); camel_content_type_set_param(ct, "smime-type", "enveloped-data"); camel_data_wrapper_set_mime_type_field(dw, ct); camel_content_type_unref(ct); camel_medium_set_content_object((CamelMedium *)opart, dw); camel_object_unref(dw); camel_mime_part_set_disposition(opart, "attachment"); camel_mime_part_set_filename(opart, "smime.p7m"); camel_mime_part_set_description(opart, "S/MIME Encrypted Message"); camel_mime_part_set_encoding(opart, CAMEL_TRANSFER_ENCODING_BASE64); return 0; fail: if (ostream) camel_object_unref(ostream); if (cmsg) NSS_CMSMessage_Destroy(cmsg); if (bulkkey) PK11_FreeSymKey(bulkkey); if (recipient_certs) { for (i=0;recipient_certs[i];i++) CERT_DestroyCertificate(recipient_certs[i]); } PORT_FreeArena(poolp, PR_FALSE); return -1; }
int main(int argc, char **argv) { CK_MECHANISM_TYPE hashMech; PK11SlotInfo* slot = NULL; PK11SymKey* SymKey = NULL; SECItem SecParam; PK11Context* HashContext = NULL; SECItem keyItem; SECStatus rv, rv1, rv2; unsigned char buf1[1024], buf2[1024]; char data[1024]; int i; unsigned int tmp2_outlen; /* Initialize NSS * * If your application code has already initialized NSS, you can skip it * * here. * * This code uses the simplest of the Init functions, which does not * * require a NSS database to exist * */ rv = NSS_NoDB_Init("."); if (rv != SECSuccess) { fprintf(stderr, "NSS initialization failed (err %d)\n", PR_GetError()); goto out; } /* choose mechanism: CKM_DES_CBC_PAD, CKM_DES3_ECB, CKM_DES3_CBC..... * * Note that some mechanisms (*_PAD) imply the padding is handled for you * * by NSS. If you choose something else, then data padding is the * * application's responsibility * */ hashMech = CKM_SHA_1_HMAC; slot = PK11_GetBestSlot(hashMech, NULL); /* slot = PK11_GetInternalKeySlot(); is a simpler alternative but in * * theory, it *may not* return the optimal slot for the operation. For * * DES ops, Internal slot is typically the best slot * */ if (slot == NULL) { fprintf(stderr, "Unable to find security device (err %d)\n", PR_GetError()); goto out; } /* NSS passes blobs around as SECItems. These contain a pointer to * * data and a length. Turn the raw key into a SECItem. */ keyItem.type = siBuffer; keyItem.data = gKey; keyItem.len = sizeof(gKey); /* Turn the raw key into a key object. We use PK11_OriginUnwrap * * to indicate the key was unwrapped - which is what should be done * * normally anyway - using raw keys isn't a good idea */ SymKey = PK11_ImportSymKey(slot, hashMech, PK11_OriginUnwrap, CKA_SIGN, &keyItem, NULL); if (SymKey == NULL) { fprintf(stderr, "Failure to import key into NSS (err %d)\n", PR_GetError()); goto out; } SecParam.type = siBuffer; SecParam.data = 0; SecParam.len = 0; /* sample data we'll hash */ strcpy(data, "Hash me!"); fprintf(stderr, "Clear Data: %s\n", data); /* ========================= START SECTION ============================= */ /* If using the the same key and iv over and over, stuff before this */ /* section and after this section needs to be done only ONCE */ /* Create cipher context */ HashContext = PK11_CreateContextBySymKey(hashMech, CKA_SIGN, SymKey, &SecParam); if (!HashContext) { fprintf(stderr, "no hash context today?\n"); goto out; } if (PK11_DigestBegin(HashContext) != SECSuccess) { fprintf(stderr, "hash doesn't begin?\n"); goto out; } rv1 = PK11_DigestOp(HashContext, (unsigned char *)data, strlen(data)+1); rv2 = PK11_DigestFinal(HashContext, buf2, &tmp2_outlen, SHA1_BLOCK_LENGTH); PK11_DestroyContext(HashContext, PR_TRUE); if (rv1 != SECSuccess || rv2 != SECSuccess) goto out; fprintf(stderr, "Hash Data: "); for (i=0; i<tmp2_outlen; i++) fprintf(stderr, "%02x ", buf2[i]); fprintf(stderr, "\n"); /* =========================== END SECTION ============================= */ /* ========================= START SECTION ============================= */ /* If using the the same key and iv over and over, stuff before this */ /* section and after this section needs to be done only ONCE */ memset(buf1, 0, sizeof(buf1)); memset(buf2, 0, sizeof(buf2)); /* Create cipher context */ HashContext = PK11_CreateContextBySymKey(hashMech, CKA_SIGN, SymKey, &SecParam); if (!HashContext) { fprintf(stderr, "no hash context today?\n"); goto out; } if (PK11_DigestBegin(HashContext) != SECSuccess) { fprintf(stderr, "hash doesn't begin?\n"); goto out; } rv1 = PK11_DigestOp(HashContext, (unsigned char *)data, 5); rv1 = PK11_DigestOp(HashContext, (unsigned char *)data+5, 4); rv2 = PK11_DigestFinal(HashContext, buf2, &tmp2_outlen, SHA1_BLOCK_LENGTH); PK11_DestroyContext(HashContext, PR_TRUE); if (rv1 != SECSuccess || rv2 != SECSuccess) goto out; fprintf(stderr, "Hash Data: "); for (i=0; i<tmp2_outlen; i++) fprintf(stderr, "%02x ", buf2[i]); fprintf(stderr, "\n"); /* =========================== END SECTION ============================= */ out: if (SymKey) PK11_FreeSymKey(SymKey); return 0; }
static int xmlSecNssKWAesOp(const xmlSecByte *key, xmlSecSize keySize, const xmlSecByte *in, xmlSecSize inSize, xmlSecByte *out, xmlSecSize outSize, int enc) { CK_MECHANISM_TYPE cipherMech; PK11SlotInfo* slot = NULL; PK11SymKey* aeskey = NULL; SECItem* SecParam = NULL; PK11Context* EncContext = NULL; SECItem keyItem; SECStatus rv; int result_len = -1; int tmp1_outlen; unsigned int tmp2_outlen; xmlSecAssert2(key != NULL, -1); xmlSecAssert2(keySize > 0, -1); xmlSecAssert2(in != NULL, -1); xmlSecAssert2(inSize > 0, -1); xmlSecAssert2(out != NULL, -1); xmlSecAssert2(outSize >= inSize + 8, -1); cipherMech = CKM_NETSCAPE_AES_KEY_WRAP; slot = PK11_GetBestSlot(cipherMech, NULL); if (slot == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_GetBestSlot", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } keyItem.data = (unsigned char *)key; keyItem.len = keySize; aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL); if (aeskey == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_ImportSymKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } SecParam = PK11_ParamFromIV(cipherMech, NULL); if (SecParam == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_ParamFromIV", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } EncContext = PK11_CreateContextBySymKey(cipherMech, enc ? CKA_ENCRYPT : CKA_DECRYPT, aeskey, SecParam); if (EncContext == NULL) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_CreateContextBySymKey", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } tmp1_outlen = tmp2_outlen = 0; rv = PK11_CipherOp(EncContext, out, &tmp1_outlen, outSize, (unsigned char *)in, inSize); if (rv != SECSuccess) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_CipherOp", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } rv = PK11_DigestFinal(EncContext, out+tmp1_outlen, &tmp2_outlen, outSize-tmp1_outlen); if (rv != SECSuccess) { xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, NULL, "PK11_DigestFinal", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } result_len = tmp1_outlen + tmp2_outlen; done: if (slot) { PK11_FreeSlot(slot); } if (aeskey) { PK11_FreeSymKey(aeskey); } if (SecParam) { SECITEM_FreeItem(SecParam, PR_TRUE); } if (EncContext) { PK11_DestroyContext(EncContext, PR_TRUE); } return(result_len); }
char * crypto_decrypt (const char *cipher, int key_type, const guint8 *data, gsize data_len, const char *iv, const gsize iv_len, const char *key, const gsize key_len, gsize *out_len, GError **error) { char *output = NULL; int decrypted_len = 0; CK_MECHANISM_TYPE cipher_mech; PK11SlotInfo *slot = NULL; SECItem key_item; PK11SymKey *sym_key = NULL; SECItem *sec_param = NULL; PK11Context *ctx = NULL; SECStatus s; gboolean success = FALSE; unsigned int pad_len = 0, extra = 0; guint32 i, real_iv_len = 0; if (!crypto_init (error)) return NULL; if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) { cipher_mech = CKM_DES3_CBC_PAD; real_iv_len = 8; } else if (!strcmp (cipher, CIPHER_DES_CBC)) { cipher_mech = CKM_DES_CBC_PAD; real_iv_len = 8; } else if (!strcmp (cipher, CIPHER_AES_CBC)) { cipher_mech = CKM_AES_CBC_PAD; real_iv_len = 16; } else { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_UNKNOWN_CIPHER, _("Private key cipher '%s' was unknown."), cipher); return NULL; } if (iv_len < real_iv_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Invalid IV length (must be at least %d)."), real_iv_len); return NULL; } output = g_malloc0 (data_len); slot = PK11_GetBestSlot (cipher_mech, NULL); if (!slot) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Failed to initialize the decryption cipher slot.")); goto out; } key_item.data = (unsigned char *) key; key_item.len = key_len; sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, NULL); if (!sym_key) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to set symmetric key for decryption.")); goto out; } key_item.data = (unsigned char *) iv; key_item.len = real_iv_len; sec_param = PK11_ParamFromIV (cipher_mech, &key_item); if (!sec_param) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to set IV for decryption.")); goto out; } ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_DECRYPT, sym_key, sec_param); if (!ctx) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to initialize the decryption context.")); goto out; } s = PK11_CipherOp (ctx, (unsigned char *) output, &decrypted_len, data_len, data, data_len); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: %d."), PORT_GetError ()); goto out; } if (decrypted_len > data_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: decrypted data too large.")); goto out; } s = PK11_DigestFinal (ctx, (unsigned char *) (output + decrypted_len), &extra, data_len - decrypted_len); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to finalize decryption of the private key: %d."), PORT_GetError ()); goto out; } decrypted_len += extra; pad_len = data_len - decrypted_len; /* Check if the padding at the end of the decrypted data is valid */ if (pad_len == 0 || pad_len > real_iv_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key: unexpected padding length.")); goto out; } /* Validate tail padding; last byte is the padding size, and all pad bytes * should contain the padding size. */ for (i = pad_len; i > 0; i--) { if (output[data_len - i] != pad_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Failed to decrypt the private key.")); goto out; } } *out_len = decrypted_len; success = TRUE; out: if (ctx) PK11_DestroyContext (ctx, PR_TRUE); if (sym_key) PK11_FreeSymKey (sym_key); if (sec_param) SECITEM_FreeItem (sec_param, PR_TRUE); if (slot) PK11_FreeSlot (slot); if (!success) { if (output) { /* Don't expose key material */ memset (output, 0, data_len); g_free (output); output = NULL; } } return output; }
char * crypto_encrypt (const char *cipher, const guint8 *data, gsize data_len, const char *iv, gsize iv_len, const char *key, gsize key_len, gsize *out_len, GError **error) { SECStatus ret; CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD; PK11SlotInfo *slot = NULL; SECItem key_item = { .data = (unsigned char *) key, .len = key_len }; SECItem iv_item = { .data = (unsigned char *) iv, .len = iv_len }; PK11SymKey *sym_key = NULL; SECItem *sec_param = NULL; PK11Context *ctx = NULL; unsigned char *output, *padded_buf; gsize output_len; int encrypted_len = 0, i; gboolean success = FALSE; gsize padded_buf_len, pad_len; if (!crypto_init (error)) return NULL; if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) cipher_mech = CKM_DES3_CBC_PAD; else if (!strcmp (cipher, CIPHER_AES_CBC)) cipher_mech = CKM_AES_CBC_PAD; else { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_UNKNOWN_CIPHER, _("Private key cipher '%s' was unknown."), cipher); return NULL; } /* If data->len % ivlen == 0, then we add another complete block * onto the end so that the decrypter knows there's padding. */ pad_len = iv_len - (data_len % iv_len); output_len = padded_buf_len = data_len + pad_len; padded_buf = g_malloc0 (padded_buf_len); memcpy (padded_buf, data, data_len); for (i = 0; i < pad_len; i++) padded_buf[data_len + i] = (guint8) (pad_len & 0xFF); output = g_malloc0 (output_len); slot = PK11_GetBestSlot (cipher_mech, NULL); if (!slot) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Failed to initialize the encryption cipher slot.")); goto out; } sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); if (!sym_key) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to set symmetric key for encryption.")); goto out; } sec_param = PK11_ParamFromIV (cipher_mech, &iv_item); if (!sec_param) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to set IV for encryption.")); goto out; } ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_ENCRYPT, sym_key, sec_param); if (!ctx) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to initialize the encryption context.")); goto out; } ret = PK11_CipherOp (ctx, output, &encrypted_len, output_len, padded_buf, padded_buf_len); if (ret != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Failed to encrypt: %d."), PORT_GetError ()); goto out; } if (encrypted_len != output_len) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_ENCRYPTION_FAILED, _("Unexpected amount of data after encrypting.")); goto out; } *out_len = encrypted_len; success = TRUE; out: if (ctx) PK11_DestroyContext (ctx, PR_TRUE); if (sym_key) PK11_FreeSymKey (sym_key); if (sec_param) SECITEM_FreeItem (sec_param, PR_TRUE); if (slot) PK11_FreeSlot (slot); memset (padded_buf, 0, padded_buf_len); g_free (padded_buf); if (!success) { memset (output, 0, output_len); g_free (output); output = NULL; } return (char *) output; } NMCryptoFileFormat crypto_verify_cert (const unsigned char *data, gsize len, GError **error) { CERTCertificate *cert; if (!crypto_init (error)) return NM_CRYPTO_FILE_FORMAT_UNKNOWN; /* Try DER/PEM first */ cert = CERT_DecodeCertFromPackage ((char *) data, len); if (!cert) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode certificate: %d"), PORT_GetError()); return NM_CRYPTO_FILE_FORMAT_UNKNOWN; } CERT_DestroyCertificate (cert); return NM_CRYPTO_FILE_FORMAT_X509; } gboolean crypto_verify_pkcs12 (const guint8 *data, gsize data_len, const char *password, GError **error) { SEC_PKCS12DecoderContext *p12ctx = NULL; SECItem pw = { 0 }; PK11SlotInfo *slot = NULL; SECStatus s; gunichar2 *ucs2_password; glong ucs2_chars = 0; #ifndef WORDS_BIGENDIAN guint16 *p; #endif /* WORDS_BIGENDIAN */ if (error) g_return_val_if_fail (*error == NULL, FALSE); if (!crypto_init (error)) return FALSE; /* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do * any conversions for us. */ if (password && *password) { if (!g_utf8_validate (password, -1, NULL)) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_PASSWORD, _("Password must be UTF-8")); return FALSE; } ucs2_password = g_utf8_to_utf16 (password, strlen (password), NULL, &ucs2_chars, NULL); /* Can't fail if g_utf8_validate() succeeded */ g_return_val_if_fail (ucs2_password != NULL && ucs2_chars != 0, FALSE); ucs2_chars *= 2; /* convert # UCS2 characters -> bytes */ pw.data = PORT_ZAlloc(ucs2_chars + 2); memcpy (pw.data, ucs2_password, ucs2_chars); pw.len = ucs2_chars + 2; /* include terminating NULL */ memset (ucs2_password, 0, ucs2_chars); g_free (ucs2_password); #ifndef WORDS_BIGENDIAN for (p = (guint16 *) pw.data; p < (guint16 *) (pw.data + pw.len); p++) *p = GUINT16_SWAP_LE_BE (*p); #endif /* WORDS_BIGENDIAN */ } else { /* NULL password */ pw.data = NULL; pw.len = 0; } slot = PK11_GetInternalKeySlot(); p12ctx = SEC_PKCS12DecoderStart (&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL); if (!p12ctx) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_FAILED, _("Couldn't initialize PKCS#12 decoder: %d"), PORT_GetError()); goto error; } s = SEC_PKCS12DecoderUpdate (p12ctx, (guint8 *)data, data_len); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA, _("Couldn't decode PKCS#12 file: %d"), PORT_GetError()); goto error; } s = SEC_PKCS12DecoderVerify (p12ctx); if (s != SECSuccess) { g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTION_FAILED, _("Couldn't verify PKCS#12 file: %d"), PORT_GetError()); goto error; } SEC_PKCS12DecoderFinish (p12ctx); SECITEM_ZfreeItem (&pw, PR_FALSE); return TRUE; error: if (p12ctx) SEC_PKCS12DecoderFinish (p12ctx); if (slot) PK11_FreeSlot(slot); SECITEM_ZfreeItem (&pw, PR_FALSE); return FALSE; }
/* * NSS_CMSEnvelopedData_Encode_BeforeStart - prepare this envelopedData for encoding * * at this point, we need * - recipientinfos set up with recipient's certificates * - a content encryption algorithm (if none, 3DES will be used) * * this function will generate a random content encryption key (aka bulk key), * initialize the recipientinfos with certificate identification and wrap the bulk key * using the proper algorithm for every certificiate. * it will finally set the bulk algorithm and key so that the encode step can find it. */ SECStatus NSS_CMSEnvelopedData_Encode_BeforeStart(NSSCMSEnvelopedData *envd) { int version; NSSCMSRecipientInfo **recipientinfos; NSSCMSContentInfo *cinfo; PK11SymKey *bulkkey = NULL; SECOidTag bulkalgtag; CK_MECHANISM_TYPE type; PK11SlotInfo *slot; SECStatus rv; SECItem *dummy; PLArenaPool *poolp; extern const SEC_ASN1Template NSSCMSRecipientInfoTemplate[]; void *mark = NULL; int i; poolp = envd->cmsg->poolp; cinfo = &(envd->contentInfo); recipientinfos = envd->recipientInfos; if (recipientinfos == NULL) { PORT_SetError(SEC_ERROR_BAD_DATA); #if 0 PORT_SetErrorString("Cannot find recipientinfos to encode."); #endif goto loser; } version = NSS_CMS_ENVELOPED_DATA_VERSION_REG; if (envd->originatorInfo != NULL || envd->unprotectedAttr != NULL) { version = NSS_CMS_ENVELOPED_DATA_VERSION_ADV; } else { for (i = 0; recipientinfos[i] != NULL; i++) { if (NSS_CMSRecipientInfo_GetVersion(recipientinfos[i]) != 0) { version = NSS_CMS_ENVELOPED_DATA_VERSION_ADV; break; } } } dummy = SEC_ASN1EncodeInteger(poolp, &(envd->version), version); if (dummy == NULL) goto loser; /* now we need to have a proper content encryption algorithm * on the SMIME level, we would figure one out by looking at SMIME capabilities * we cannot do that on our level, so if none is set already, we'll just go * with one of the mandatory algorithms (3DES) */ if ((bulkalgtag = NSS_CMSContentInfo_GetContentEncAlgTag(cinfo)) == SEC_OID_UNKNOWN) { rv = NSS_CMSContentInfo_SetContentEncAlg(poolp, cinfo, SEC_OID_DES_EDE3_CBC, NULL, 168); if (rv != SECSuccess) goto loser; bulkalgtag = SEC_OID_DES_EDE3_CBC; } /* generate a random bulk key suitable for content encryption alg */ type = PK11_AlgtagToMechanism(bulkalgtag); slot = PK11_GetBestSlot(type, envd->cmsg->pwfn_arg); if (slot == NULL) goto loser; /* error has been set by PK11_GetBestSlot */ /* this is expensive... */ bulkkey = PK11_KeyGen(slot, type, NULL, NSS_CMSContentInfo_GetBulkKeySize(cinfo) / 8, envd->cmsg->pwfn_arg); PK11_FreeSlot(slot); if (bulkkey == NULL) goto loser; /* error has been set by PK11_KeyGen */ mark = PORT_ArenaMark(poolp); /* Encrypt the bulk key with the public key of each recipient. */ for (i = 0; recipientinfos[i] != NULL; i++) { rv = NSS_CMSRecipientInfo_WrapBulkKey(recipientinfos[i], bulkkey, bulkalgtag); if (rv != SECSuccess) goto loser; /* error has been set by NSS_CMSRecipientInfo_EncryptBulkKey */ /* could be: alg not supported etc. */ } /* the recipientinfos are all finished. now sort them by DER for SET OF encoding */ rv = NSS_CMSArray_SortByDER((void **)envd->recipientInfos, NSSCMSRecipientInfoTemplate, NULL); if (rv != SECSuccess) goto loser; /* error has been set by NSS_CMSArray_SortByDER */ /* store the bulk key in the contentInfo so that the encoder can find it */ NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey); PORT_ArenaUnmark(poolp, mark); PK11_FreeSymKey(bulkkey); return SECSuccess; loser: if (mark != NULL) PORT_ArenaRelease (poolp, mark); if (bulkkey) PK11_FreeSymKey(bulkkey); return SECFailure; }
/* MUST BE THREAD-SAFE */ void calc_ke(struct pluto_crypto_req *r) { SECKEYDHParams dhp; PK11SlotInfo *slot = NULL; SECKEYPrivateKey *privk; SECKEYPublicKey *pubk; struct pcr_kenonce *kn = &r->pcr_d.kn; const struct oakley_group_desc *group = lookup_group(kn->oakley_group); chunk_t base = mpz_to_n_autosize(group->generator); chunk_t prime = mpz_to_n_autosize(group->modulus); DBG(DBG_CRYPT, DBG_dump_chunk("NSS: Value of Prime:", prime)); DBG(DBG_CRYPT, DBG_dump_chunk("NSS: Value of base:", base)); dhp.prime.data = prime.ptr; dhp.prime.len = prime.len; dhp.base.data = base.ptr; dhp.base.len = base.len; slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN, lsw_return_nss_password_file_info()); if (slot == NULL) loglog(RC_LOG_SERIOUS, "NSS: slot for DH key gen is NULL"); passert(slot != NULL); for (;;) { pubk = NULL; /* ??? is this needed? Output-only from next call? */ privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, &dhp, &pubk, PR_FALSE, PR_TRUE, lsw_return_nss_password_file_info()); if (privk == NULL) { loglog(RC_LOG_SERIOUS, "NSS: DH private key creation failed (err %d)", PR_GetError()); } passert(privk != NULL && pubk != NULL); if (group->bytes == pubk->u.dh.publicValue.len) { DBG(DBG_CRYPT, DBG_log("NSS: generated dh priv and pub keys: %d", pubk->u.dh.publicValue.len)); break; } else { DBG(DBG_CRYPT, DBG_log("NSS: generating dh priv and pub keys again")); SECKEY_DestroyPrivateKey(privk); SECKEY_DestroyPublicKey(pubk); } } kn->secret = privk; kn->pubk = pubk; ALLOC_WIRE_CHUNK(*kn, gi, pubk->u.dh.publicValue.len); { unsigned char *gip = WIRE_CHUNK_PTR(*kn, gi); memcpy(gip, pubk->u.dh.publicValue.data, pubk->u.dh.publicValue.len); } DBG(DBG_CRYPT, { DBG_log("NSS: Local DH secret (pointer): %p", kn->secret); DBG_dump("NSS: Public DH value sent(computed in NSS):", WIRE_CHUNK_PTR(*kn, gi), pubk->u.dh.publicValue.len); });
/** * @brief Create a key from the given passphrase. By default, the PBKDF2 * algorithm is used to generate the key from the passphrase. It is expected * that the same pass phrase will generate the same key, regardless of the * backend crypto platform used. The key is cleaned up when the context * is cleaned, and may be reused with multiple encryption or decryption * operations. * @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If * *key is not NULL, *key must point at a previously created structure. * @param key The key returned, see note. * @param ivSize The size of the initialisation vector will be returned, based * on whether an IV is relevant for this type of crypto. * @param pass The passphrase to use. * @param passLen The passphrase length in bytes * @param salt The salt to use. * @param saltLen The salt length in bytes * @param type 3DES_192, AES_128, AES_192, AES_256. * @param mode Electronic Code Book / Cipher Block Chaining. * @param doPad Pad if necessary. * @param iterations Iteration count * @param f The context to use. * @param p The pool to use. * @return Returns APR_ENOKEY if the pass phrase is missing or empty, or if a backend * error occurred while generating the key. APR_ENOCIPHER if the type or mode * is not supported by the particular backend. APR_EKEYTYPE if the key type is * not known. APR_EPADDING if padding was requested but is not supported. * APR_ENOTIMPL if not implemented. */ static apr_status_t crypto_passphrase(apr_crypto_key_t **k, apr_size_t *ivSize, const char *pass, apr_size_t passLen, const unsigned char * salt, apr_size_t saltLen, const apr_crypto_block_key_type_e type, const apr_crypto_block_key_mode_e mode, const int doPad, const int iterations, const apr_crypto_t *f, apr_pool_t *p) { apr_status_t rv = APR_SUCCESS; PK11SlotInfo * slot; SECItem passItem; SECItem saltItem; SECAlgorithmID *algid; void *wincx = NULL; /* what is wincx? */ apr_crypto_key_t *key = *k; if (!key) { *k = key = apr_array_push(f->keys); } if (!key) { return APR_ENOMEM; } key->f = f; key->provider = f->provider; /* decide on what cipher mechanism we will be using */ switch (type) { case (APR_KEY_3DES_192): if (APR_MODE_CBC == mode) { key->cipherOid = SEC_OID_DES_EDE3_CBC; } else if (APR_MODE_ECB == mode) { return APR_ENOCIPHER; /* No OID for CKM_DES3_ECB; */ } break; case (APR_KEY_AES_128): if (APR_MODE_CBC == mode) { key->cipherOid = SEC_OID_AES_128_CBC; } else { key->cipherOid = SEC_OID_AES_128_ECB; } break; case (APR_KEY_AES_192): if (APR_MODE_CBC == mode) { key->cipherOid = SEC_OID_AES_192_CBC; } else { key->cipherOid = SEC_OID_AES_192_ECB; } break; case (APR_KEY_AES_256): if (APR_MODE_CBC == mode) { key->cipherOid = SEC_OID_AES_256_CBC; } else { key->cipherOid = SEC_OID_AES_256_ECB; } break; default: /* unknown key type, give up */ return APR_EKEYTYPE; } /* AES_128_CBC --> CKM_AES_CBC --> CKM_AES_CBC_PAD */ key->cipherMech = PK11_AlgtagToMechanism(key->cipherOid); if (key->cipherMech == CKM_INVALID_MECHANISM) { return APR_ENOCIPHER; } if (doPad) { CK_MECHANISM_TYPE paddedMech; paddedMech = PK11_GetPadMechanism(key->cipherMech); if (CKM_INVALID_MECHANISM == paddedMech || key->cipherMech == paddedMech) { return APR_EPADDING; } key->cipherMech = paddedMech; } /* Turn the raw passphrase and salt into SECItems */ passItem.data = (unsigned char*) pass; passItem.len = passLen; saltItem.data = (unsigned char*) salt; saltItem.len = saltLen; /* generate the key */ /* pbeAlg and cipherAlg are the same. NSS decides the keylength. */ algid = PK11_CreatePBEV2AlgorithmID(key->cipherOid, key->cipherOid, SEC_OID_HMAC_SHA1, 0, iterations, &saltItem); if (algid) { slot = PK11_GetBestSlot(key->cipherMech, wincx); if (slot) { key->symKey = PK11_PBEKeyGen(slot, algid, &passItem, PR_FALSE, wincx); PK11_FreeSlot(slot); } SECOID_DestroyAlgorithmID(algid, PR_TRUE); } /* sanity check? */ if (!key->symKey) { PRErrorCode perr = PORT_GetError(); if (perr) { f->result->rc = perr; f->result->msg = PR_ErrorToName(perr); rv = APR_ENOKEY; } } key->ivSize = PK11_GetIVLength(key->cipherMech); if (ivSize) { *ivSize = key->ivSize; } return rv; }
static gchar* cipher_pbkdf2_nss_sha1(const gchar *passphrase, const gchar *salt, guint iter_count, guint out_len) { PK11SlotInfo *slot; SECAlgorithmID *algorithm = NULL; PK11SymKey *symkey = NULL; const SECItem *symkey_data = NULL; SECItem salt_item, passphrase_item; guchar *passphrase_buff, *salt_buff; gchar *ret; g_return_val_if_fail(passphrase != NULL, NULL); g_return_val_if_fail(iter_count > 0, NULL); g_return_val_if_fail(out_len > 0, NULL); NSS_NoDB_Init(NULL); slot = PK11_GetBestSlot(PK11_AlgtagToMechanism(SEC_OID_PKCS5_PBKDF2), NULL); if (slot == NULL) { purple_debug_error("cipher-test", "NSS: couldn't get slot: " "%d\n", PR_GetError()); return NULL; } salt_buff = (guchar*)g_strdup(salt ? salt : ""); salt_item.type = siBuffer; salt_item.data = salt_buff; salt_item.len = salt ? strlen(salt) : 0; algorithm = PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2, SEC_OID_AES_256_CBC, SEC_OID_HMAC_SHA1, out_len, iter_count, &salt_item); if (algorithm == NULL) { purple_debug_error("cipher-test", "NSS: couldn't create " "algorithm ID: %d\n", PR_GetError()); PK11_FreeSlot(slot); g_free(salt_buff); return NULL; } passphrase_buff = (guchar*)g_strdup(passphrase); passphrase_item.type = siBuffer; passphrase_item.data = passphrase_buff; passphrase_item.len = strlen(passphrase); symkey = PK11_PBEKeyGen(slot, algorithm, &passphrase_item, PR_FALSE, NULL); if (symkey == NULL) { purple_debug_error("cipher-test", "NSS: Couldn't generate key: " "%d\n", PR_GetError()); SECOID_DestroyAlgorithmID(algorithm, PR_TRUE); PK11_FreeSlot(slot); g_free(passphrase_buff); g_free(salt_buff); return NULL; } if (PK11_ExtractKeyValue(symkey) == SECSuccess) symkey_data = PK11_GetKeyData(symkey); if (symkey_data == NULL || symkey_data->data == NULL) { purple_debug_error("cipher-test", "NSS: Couldn't extract key " "value: %d\n", PR_GetError()); PK11_FreeSymKey(symkey); SECOID_DestroyAlgorithmID(algorithm, PR_TRUE); PK11_FreeSlot(slot); g_free(passphrase_buff); g_free(salt_buff); return NULL; } if (symkey_data->len != out_len) { purple_debug_error("cipher-test", "NSS: Invalid key length: %d " "(should be %d)\n", symkey_data->len, out_len); PK11_FreeSymKey(symkey); SECOID_DestroyAlgorithmID(algorithm, PR_TRUE); PK11_FreeSlot(slot); g_free(passphrase_buff); g_free(salt_buff); return NULL; } ret = purple_base16_encode(symkey_data->data, symkey_data->len); PK11_FreeSymKey(symkey); SECOID_DestroyAlgorithmID(algorithm, PR_TRUE); PK11_FreeSlot(slot); g_free(passphrase_buff); g_free(salt_buff); return ret; }
SECStatus SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert, const CERTCertificateList *certChainOpt, SECKEYPrivateKey *key, SSL3KEAType kea) { sslSocket *ss; SECKEYPublicKey *pubKey = NULL; ssl3KeyPair *keyPair = NULL; SECStatus rv = SECFailure; ss = ssl_FindSocket(fd); if (!ss) { return SECFailure; } if (!cert != !key) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } if ((kea >= kt_kea_size) || (kea < kt_null)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); return SECFailure; } if (kea != NSS_FindCertKEAType(cert)) { PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH); return SECFailure; } if (cert) { pubKey = CERT_ExtractPublicKey(cert); if (!pubKey) return SECFailure; } if (key) { SECKEYPrivateKey * keyCopy = NULL; CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM; if (key->pkcs11Slot) { PK11SlotInfo * bestSlot; bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyMech = PK11_MapSignKeyType(key->keyType); if (keyMech != CKM_INVALID_MECHANISM) { PK11SlotInfo * bestSlot; bestSlot = PK11_GetBestSlot(keyMech, NULL ); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyCopy = SECKEY_CopyPrivateKey(key); if (keyCopy == NULL) goto loser; keyPair = ssl3_NewKeyPair(keyCopy, pubKey); if (keyPair == NULL) { SECKEY_DestroyPrivateKey(keyCopy); goto loser; } pubKey = NULL; } if (ssl_ConfigSecureServer(ss, cert, certChainOpt, keyPair, kea) == SECFailure) { goto loser; } if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce, &serverCAListSetup, (void *)(ss->dbHandle))) { rv = SECSuccess; } loser: if (keyPair) { ssl3_FreeKeyPair(keyPair); } if (pubKey) { SECKEY_DestroyPublicKey(pubKey); pubKey = NULL; } return rv; }
size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len, const unsigned char *input, size_t input_len, const unsigned char *iv, unsigned char **res) { #define CIPHER_MECH CKM_DES3_CBC #define MAX_OUTPUT_LEN 72 int len1; unsigned int len2; PK11Context *ctx = NULL; PK11SlotInfo *slot = NULL; SECItem keyItem; SECItem ivItem; SECItem *secParam = NULL; PK11SymKey *symKey = NULL; size_t rc; SECStatus rv; if (!initialized) { ssl_init(); } keyItem.data = (unsigned char *)key; keyItem.len = key_len; slot = PK11_GetBestSlot(CIPHER_MECH, NULL); if (slot == NULL) { fprintf(stderr, "PK11_GetBestSlot failed (err %d)\n", PR_GetError()); rc = 0; goto out; } symKey = PK11_ImportSymKey(slot, CIPHER_MECH, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL); if (symKey == NULL) { fprintf(stderr, "PK11_ImportSymKey failed (err %d)\n", PR_GetError()); rc = 0; goto out; } ivItem.data = (unsigned char *)iv; /* See msn_soap_passport_sso_handle_response in protocols/msn/soap.c */ ivItem.len = 8; secParam = PK11_ParamFromIV(CIPHER_MECH, &ivItem); if (secParam == NULL) { fprintf(stderr, "PK11_ParamFromIV failed (err %d)\n", PR_GetError()); rc = 0; goto out; } ctx = PK11_CreateContextBySymKey(CIPHER_MECH, CKA_ENCRYPT, symKey, secParam); if (ctx == NULL) { fprintf(stderr, "PK11_CreateContextBySymKey failed (err %d)\n", PR_GetError()); rc = 0; goto out; } *res = g_new0(unsigned char, MAX_OUTPUT_LEN); rv = PK11_CipherOp(ctx, *res, &len1, MAX_OUTPUT_LEN, (unsigned char *)input, input_len); if (rv != SECSuccess) { fprintf(stderr, "PK11_CipherOp failed (err %d)\n", PR_GetError()); rc = 0; goto out; } assert(len1 <= MAX_OUTPUT_LEN); rv = PK11_DigestFinal(ctx, *res + len1, &len2, (unsigned int)MAX_OUTPUT_LEN - len1); if (rv != SECSuccess) { fprintf(stderr, "PK11_DigestFinal failed (err %d)\n", PR_GetError()); rc = 0; goto out; } rc = len1 + len2; out: if (ctx) PK11_DestroyContext(ctx, PR_TRUE); if (symKey) PK11_FreeSymKey(symKey); if (secParam) SECITEM_FreeItem(secParam, PR_TRUE); if (slot) PK11_FreeSlot(slot); return rc; }
static gboolean purple_aes_cipher_nss_crypt(const guchar *input, guchar *output, size_t len, guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size, CK_ATTRIBUTE_TYPE operation) { PurpleAESCipherNSSContext context; CK_MECHANISM_TYPE cipher_mech = CKM_AES_CBC; SECItem key_item, iv_item; SECStatus ret; int outlen = 0; unsigned int outlen_tmp = 0; memset(&context, 0, sizeof(PurpleAESCipherNSSContext)); if (NSS_NoDB_Init(NULL) != SECSuccess) { purple_debug_error("cipher-aes", "NSS_NoDB_Init failed: %d\n", PR_GetError()); return FALSE; } context.slot = PK11_GetBestSlot(cipher_mech, NULL); if (context.slot == NULL) { purple_debug_error("cipher-aes", "PK11_GetBestSlot failed: %d\n", PR_GetError()); return FALSE; } key_item.type = siBuffer; key_item.data = key; key_item.len = key_size; context.sym_key = PK11_ImportSymKey(context.slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL); if (context.sym_key == NULL) { purple_debug_error("cipher-aes", "PK11_ImportSymKey failed: %d\n", PR_GetError()); purple_aes_cipher_nss_cleanup(&context); return FALSE; } iv_item.type = siBuffer; iv_item.data = iv; iv_item.len = PURPLE_AES_BLOCK_SIZE; context.sec_param = PK11_ParamFromIV(cipher_mech, &iv_item); if (context.sec_param == NULL) { purple_debug_error("cipher-aes", "PK11_ParamFromIV failed: %d\n", PR_GetError()); purple_aes_cipher_nss_cleanup(&context); return FALSE; } context.enc_context = PK11_CreateContextBySymKey(cipher_mech, operation, context.sym_key, context.sec_param); if (context.enc_context == NULL) { purple_debug_error("cipher-aes", "PK11_CreateContextBySymKey failed: %d\n", PR_GetError()); purple_aes_cipher_nss_cleanup(&context); return FALSE; } ret = PK11_CipherOp(context.enc_context, output, &outlen, len, (guchar *)input, len); if (ret != SECSuccess) { purple_debug_error("cipher-aes", "PK11_CipherOp failed: %d\n", PR_GetError()); purple_aes_cipher_nss_cleanup(&context); return FALSE; } ret = PK11_DigestFinal(context.enc_context, output + outlen, &outlen_tmp, len - outlen); if (ret != SECSuccess) { purple_debug_error("cipher-aes", "PK11_DigestFinal failed: %d\n", PR_GetError()); purple_aes_cipher_nss_cleanup(&context); return FALSE; } purple_aes_cipher_nss_cleanup(&context); outlen += outlen_tmp; if (outlen != (int)len) { purple_debug_error("cipher-aes", "resulting length doesn't match: %d (expected: %lu)\n", outlen, len); return FALSE; } return TRUE; }
static sec_PKCS7CipherObject * sec_pkcs7_encoder_start_encrypt (SEC_PKCS7ContentInfo *cinfo, PK11SymKey *orig_bulkkey) { SECOidTag kind; sec_PKCS7CipherObject *encryptobj; SEC_PKCS7RecipientInfo **recipientinfos, *ri; SEC_PKCS7EncryptedContentInfo *enccinfo; SECKEYPublicKey *publickey = NULL; SECKEYPrivateKey *ourPrivKey = NULL; PK11SymKey *bulkkey; void *mark, *wincx; int i; PLArenaPool *arena = NULL; /* Get the context in case we need it below. */ wincx = cinfo->pwfn_arg; kind = SEC_PKCS7ContentType (cinfo); switch (kind) { default: case SEC_OID_PKCS7_DATA: case SEC_OID_PKCS7_DIGESTED_DATA: case SEC_OID_PKCS7_SIGNED_DATA: recipientinfos = NULL; enccinfo = NULL; break; case SEC_OID_PKCS7_ENCRYPTED_DATA: { SEC_PKCS7EncryptedData *encdp; /* To do EncryptedData we *must* be given a bulk key. */ PORT_Assert (orig_bulkkey != NULL); if (orig_bulkkey == NULL) { /* XXX error? */ return NULL; } encdp = cinfo->content.encryptedData; recipientinfos = NULL; enccinfo = &(encdp->encContentInfo); } break; case SEC_OID_PKCS7_ENVELOPED_DATA: { SEC_PKCS7EnvelopedData *envdp; envdp = cinfo->content.envelopedData; recipientinfos = envdp->recipientInfos; enccinfo = &(envdp->encContentInfo); } break; case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: { SEC_PKCS7SignedAndEnvelopedData *saedp; saedp = cinfo->content.signedAndEnvelopedData; recipientinfos = saedp->recipientInfos; enccinfo = &(saedp->encContentInfo); } break; } if (enccinfo == NULL) return NULL; bulkkey = orig_bulkkey; if (bulkkey == NULL) { CK_MECHANISM_TYPE type = PK11_AlgtagToMechanism(enccinfo->encalg); PK11SlotInfo *slot; slot = PK11_GetBestSlot(type,cinfo->pwfn_arg); if (slot == NULL) { return NULL; } bulkkey = PK11_KeyGen(slot,type,NULL, enccinfo->keysize/8, cinfo->pwfn_arg); PK11_FreeSlot(slot); if (bulkkey == NULL) { return NULL; } } encryptobj = NULL; mark = PORT_ArenaMark (cinfo->poolp); /* * Encrypt the bulk key with the public key of each recipient. */ for (i = 0; recipientinfos && (ri = recipientinfos[i]) != NULL; i++) { CERTCertificate *cert; SECOidTag certalgtag, encalgtag; SECStatus rv; int data_len; SECItem *params = NULL; cert = ri->cert; PORT_Assert (cert != NULL); if (cert == NULL) continue; /* * XXX Want an interface that takes a cert and some data and * fills in an algorithmID and encrypts the data with the public * key from the cert. Or, give me two interfaces -- one which * gets the algorithm tag from a cert (I should not have to go * down into the subjectPublicKeyInfo myself) and another which * takes a public key and algorithm tag and data and encrypts * the data. Or something like that. The point is that all * of the following hardwired RSA stuff should be done elsewhere. */ certalgtag=SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm)); switch (certalgtag) { case SEC_OID_PKCS1_RSA_ENCRYPTION: encalgtag = certalgtag; publickey = CERT_ExtractPublicKey (cert); if (publickey == NULL) goto loser; data_len = SECKEY_PublicKeyStrength(publickey); ri->encKey.data = (unsigned char*)PORT_ArenaAlloc(cinfo->poolp ,data_len); ri->encKey.len = data_len; if (ri->encKey.data == NULL) goto loser; rv = PK11_PubWrapSymKey(PK11_AlgtagToMechanism(certalgtag),publickey, bulkkey,&ri->encKey); SECKEY_DestroyPublicKey(publickey); publickey = NULL; if (rv != SECSuccess) goto loser; params = NULL; /* paranoia */ break; default: PORT_SetError (SEC_ERROR_INVALID_ALGORITHM); goto loser; } rv = SECOID_SetAlgorithmID(cinfo->poolp, &ri->keyEncAlg, encalgtag, params); if (rv != SECSuccess) goto loser; if (arena) PORT_FreeArena(arena,PR_FALSE); arena = NULL; } encryptobj = sec_PKCS7CreateEncryptObject (cinfo->poolp, bulkkey, enccinfo->encalg, &(enccinfo->contentEncAlg)); if (encryptobj != NULL) { PORT_ArenaUnmark (cinfo->poolp, mark); mark = NULL; /* good one; do not want to release */ } /* fallthru */ loser: if (arena) { PORT_FreeArena(arena, PR_FALSE); } if (publickey) { SECKEY_DestroyPublicKey(publickey); } if (ourPrivKey) { SECKEY_DestroyPrivateKey(ourPrivKey); } if (mark != NULL) { PORT_ArenaRelease (cinfo->poolp, mark); } if (orig_bulkkey == NULL) { if (bulkkey) PK11_FreeSymKey(bulkkey); } return encryptobj; }
SECStatus SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert, SECKEYPrivateKey *key, SSL3KEAType kea) { SECStatus rv; sslSocket *ss; sslServerCerts *sc; SECKEYPublicKey * pubKey = NULL; ss = ssl_FindSocket(fd); if (!ss) { return SECFailure; } /* Both key and cert must have a value or be NULL */ /* Passing a value of NULL will turn off key exchange algorithms that were * previously turned on */ if (!cert != !key) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } /* make sure the key exchange is recognized */ if ((kea >= kt_kea_size) || (kea < kt_null)) { PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); return SECFailure; } if (kea != ssl_FindCertKEAType(cert)) { PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH); return SECFailure; } sc = ss->serverCerts + kea; /* load the server certificate */ if (sc->serverCert != NULL) { CERT_DestroyCertificate(sc->serverCert); sc->serverCert = NULL; } if (cert) { sc->serverCert = CERT_DupCertificate(cert); if (!sc->serverCert) goto loser; /* get the size of the cert's public key, and remember it */ pubKey = CERT_ExtractPublicKey(cert); if (!pubKey) goto loser; sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey); } /* load the server cert chain */ if (sc->serverCertChain != NULL) { CERT_DestroyCertificateList(sc->serverCertChain); sc->serverCertChain = NULL; } if (cert) { sc->serverCertChain = CERT_CertChainFromCert( sc->serverCert, certUsageSSLServer, PR_TRUE); if (sc->serverCertChain == NULL) goto loser; } /* load the private key */ if (sc->serverKeyPair != NULL) { ssl3_FreeKeyPair(sc->serverKeyPair); sc->serverKeyPair = NULL; } if (key) { SECKEYPrivateKey * keyCopy = NULL; CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM; if (key->pkcs11Slot) { PK11SlotInfo * bestSlot; bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyMech = PK11_MapSignKeyType(key->keyType); if (keyMech != CKM_INVALID_MECHANISM) { PK11SlotInfo * bestSlot; /* XXX Maybe should be bestSlotMultiple? */ bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */); if (bestSlot) { keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); PK11_FreeSlot(bestSlot); } } if (keyCopy == NULL) keyCopy = SECKEY_CopyPrivateKey(key); if (keyCopy == NULL) goto loser; SECKEY_CacheStaticFlags(keyCopy); sc->serverKeyPair = ssl3_NewKeyPair(keyCopy, pubKey); if (sc->serverKeyPair == NULL) { SECKEY_DestroyPrivateKey(keyCopy); goto loser; } pubKey = NULL; /* adopted by serverKeyPair */ } if (kea == kt_rsa && cert && sc->serverKeyBits > 512) { if (ss->opt.noStepDown) { /* disable all export ciphersuites */ } else { rv = ssl3_CreateRSAStepDownKeys(ss); if (rv != SECSuccess) { return SECFailure; /* err set by ssl3_CreateRSAStepDownKeys */ } } } /* Only do this once because it's global. */ if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce, &serverCAListSetup, (void *)(ss->dbHandle))) { return SECSuccess; } loser: if (pubKey) { SECKEY_DestroyPublicKey(pubKey); pubKey = NULL; } if (sc->serverCert != NULL) { CERT_DestroyCertificate(sc->serverCert); sc->serverCert = NULL; } if (sc->serverCertChain != NULL) { CERT_DestroyCertificateList(sc->serverCertChain); sc->serverCertChain = NULL; } if (sc->serverKeyPair != NULL) { ssl3_FreeKeyPair(sc->serverKeyPair); sc->serverKeyPair = NULL; } return SECFailure; }
int nss_ctx_init(TALLOC_CTX *mem_ctx, struct crypto_mech_data *mech_props, uint8_t *key, int keylen, uint8_t *iv, int ivlen, struct sss_nss_crypto_ctx **_cctx) { struct sss_nss_crypto_ctx *cctx; int ret; cctx = talloc_zero(mem_ctx, struct sss_nss_crypto_ctx); if (!cctx) { return ENOMEM; } talloc_set_destructor(cctx, sss_nss_crypto_ctx_destructor); cctx->slot = PK11_GetBestSlot(mech_props->cipher, NULL); if (cctx->slot == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Unable to find security device (err %d)\n", PR_GetError()); ret = EIO; goto done; } if (keylen > 0) { cctx->key = talloc(cctx, SECItem); if (cctx->key == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to allocate Key buffer\n"); ret = ENOMEM; goto done; } if (key) { MAKE_SECITEM(key, keylen, cctx->key); } else { ret = generate_random_key(cctx, cctx->slot, mech_props, &cctx->key); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not generate encryption key\n"); goto done; } } } if (ivlen > 0) { cctx->iv = talloc(cctx, SECItem); if (cctx->iv == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to allocate IV buffer\n"); ret = ENOMEM; goto done; } if (iv) { MAKE_SECITEM(iv, ivlen, cctx->iv); } else { ret = generate_random_key(cctx, cctx->slot, mech_props, &cctx->iv); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not generate initialization vector\n"); goto done; } } } ret = EOK; *_cctx = cctx; done: if (ret) talloc_zfree(cctx); return ret; }
void calc_ke(struct pluto_crypto_req *r) { chunk_t prime; chunk_t base; SECKEYDHParams dhp; PK11SlotInfo *slot = NULL; SECKEYPrivateKey *privk; SECKEYPublicKey *pubk; struct pcr_kenonce *kn = &r->pcr_d.kn; const struct oakley_group_desc *group; group = lookup_group(kn->oakley_group); base = mpz_to_n2(group->generator); prime = mpz_to_n2(group->modulus); DBG(DBG_CRYPT,DBG_dump_chunk("NSS: Value of Prime:\n", prime)); DBG(DBG_CRYPT,DBG_dump_chunk("NSS: Value of base:\n", base)); dhp.prime.data=prime.ptr; dhp.prime.len=prime.len; dhp.base.data=base.ptr; dhp.base.len=base.len; slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,osw_return_nss_password_file_info()); if(!slot) { loglog(RC_LOG_SERIOUS, "NSS: slot for DH key gen is NULL"); } PR_ASSERT(slot!=NULL); while(1) { privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, &dhp, &pubk, PR_FALSE, PR_TRUE, osw_return_nss_password_file_info()); if(!privk) { loglog(RC_LOG_SERIOUS, "NSS: DH private key creation failed (err %d)", PR_GetError()); } PR_ASSERT(privk!=NULL); if( group-> bytes == pubk->u.dh.publicValue.len ) { DBG(DBG_CRYPT, DBG_log("NSS: generated dh priv and pub keys: %d\n", pubk->u.dh.publicValue.len)); break; } else { DBG(DBG_CRYPT, DBG_log("NSS: generating dh priv and pub keys")); if (privk) SECKEY_DestroyPrivateKey(privk); if (pubk) SECKEY_DestroyPublicKey(pubk); } } pluto_crypto_allocchunk(&kn->thespace, &kn->secret, sizeof(SECKEYPrivateKey*)); { char *gip = wire_chunk_ptr(kn, &(kn->secret)); memcpy(gip, &privk, sizeof(SECKEYPrivateKey *)); } pluto_crypto_allocchunk(&kn->thespace, &kn->gi, pubk->u.dh.publicValue.len); { char *gip = wire_chunk_ptr(kn, &(kn->gi)); memcpy(gip, pubk->u.dh.publicValue.data, pubk->u.dh.publicValue.len); } pluto_crypto_allocchunk(&kn->thespace, &kn->pubk, sizeof(SECKEYPublicKey*)); { char *gip = wire_chunk_ptr(kn, &(kn->pubk)); memcpy(gip, &pubk, sizeof(SECKEYPublicKey*)); } DBG(DBG_CRYPT, DBG_dump("NSS: Local DH secret:\n" , wire_chunk_ptr(kn, &(kn->secret)) , sizeof(SECKEYPrivateKey*)); DBG_dump("NSS: Public DH value sent(computed in NSS):\n", wire_chunk_ptr(kn, &(kn->gi)),pubk->u.dh.publicValue.len)); DBG(DBG_CRYPT, DBG_dump("NSS: Local DH public value (pointer):\n" , wire_chunk_ptr(kn, &(kn->pubk)) , sizeof(SECKEYPublicKey*))); /* clean up after ourselves */ if (slot) { PK11_FreeSlot(slot); } /* if (privk){SECKEY_DestroyPrivateKey(privk);} */ /* if (pubk){SECKEY_DestroyPublicKey(pubk);} */ freeanychunk(prime); freeanychunk(base); }