static bool test_ctr_op(const struct encrypt_desc *encrypt_desc, const char *description, int encrypt, PK11SymKey *sym_key, const char *encoded_cb, const char *output_cb, const char *input_name, const char *input, const char *output_name, const char *output) { const char *op = encrypt ? "encrypt" : "decrypt"; bool ok = TRUE; chunk_t cb = decode_to_chunk("input counter-block: ", encoded_cb); chunk_t tmp = decode_to_chunk(input_name, input); chunk_t expected_output = decode_to_chunk(output_name, output); chunk_t expected_cb = decode_to_chunk("expected counter-block: ", output_cb); /* do_crypt modifies the data and IV in place. */ encrypt_desc->encrypt_ops->do_crypt(encrypt_desc, tmp.ptr, tmp.len, sym_key, cb.ptr, encrypt); if (!verify_chunk(op, expected_output, tmp)) { DBG(DBG_CRYPT, DBG_log("test_ctr_op: %s: %s: output does not match", description, op)); ok = FALSE; } if (!verify_chunk("counter-block", expected_cb, cb)) { DBG(DBG_CRYPT, DBG_log("test_ctr_op: %s: %s: counter-block does not match", description, op)); ok = FALSE; } freeanychunk(cb); freeanychunk(expected_cb); freeanychunk(tmp); freeanychunk(expected_output); return ok; }
/* * Processing FOR KE values. */ void unpack_KE(struct state *st , struct pluto_crypto_req *r , chunk_t *g) { struct pcr_kenonce *kn = &r->pcr_d.kn; if (!st->st_sec_in_use) { st->st_sec_in_use = TRUE; freeanychunk(*g); /* happens in odd error cases */ clonetochunk(*g, wire_chunk_ptr(kn, &(kn->gi)) , kn->gi.len, "saved gi value"); #ifdef HAVE_LIBNSS DBG(DBG_CRYPT, DBG_log("saving DH priv (local secret) and pub key into state struc")); clonetochunk(st->st_sec_chunk , wire_chunk_ptr(kn, &(kn->secret)) , kn->secret.len, "pointer to DH private key (secret)"); clonetochunk(st->pubk , wire_chunk_ptr(kn, &(kn->pubk)) , kn->pubk.len, "pointer to DH public key"); #else n_to_mpz(&st->st_sec , wire_chunk_ptr(kn, &(kn->secret)) , kn->secret.len); clonetochunk(st->st_sec_chunk , wire_chunk_ptr(kn, &(kn->secret)) , kn->secret.len, "long term secret"); #endif } }
void unpack_nonce(chunk_t *n, const struct pluto_crypto_req *r) { const struct pcr_kenonce *kn = &r->pcr_d.kn; freeanychunk(*n); clonetochunk(*n, WIRE_CHUNK_PTR(*kn, n), DEFAULT_NONCE_SIZE, "initiator nonce"); }
void unpack_nonce(chunk_t *n, struct pluto_crypto_req *r) { struct pcr_kenonce *kn = &r->pcr_d.kn; freeanychunk(*n); clonetochunk(*n, wire_chunk_ptr(kn, &(kn->n)), DEFAULT_NONCE_SIZE, "initiator nonce"); }
/* * Turn the raw key into a SECItem and then SymKey. * * Since slots are referenced counted and ImportSymKey adds a * reference, immediate freeing of the local slot is possible. * * ImportSymKey makes a copy of the key chunk so that can also be * released. */ PK11SymKey *decode_to_key(CK_MECHANISM_TYPE cipher_mechanism, const char *encoded_key) { chunk_t raw_key = decode_to_chunk("key", encoded_key); PK11SymKey *sym_key = chunk_to_symkey(cipher_mechanism, raw_key); freeanychunk(raw_key); return sym_key; }
static void monte_run(void) { print_chunk("Seed", seed, 0); chunk_t MDi_3 = alloc_chunk(seed.len, "MDi_3"); chunk_t MDi_2 = alloc_chunk(seed.len, "MDi_2"); chunk_t MDi_1 = alloc_chunk(seed.len, "MDi_1"); chunk_t Mi = alloc_chunk(3 * seed.len, "Mi"); for (int j = 0; j < 100; j++) { //MD[0] = MD[1] = MD[2] = Seed memcpy(MDi_3.ptr, seed.ptr, seed.len); memcpy(MDi_2.ptr, seed.ptr, seed.len); memcpy(MDi_1.ptr, seed.ptr, seed.len); for (int i = 3; i < 1003; i++) { // shuffle chunk_t tmp = MDi_3; MDi_3 = MDi_2; MDi_2 = MDi_1; MDi_1 = seed; seed = tmp; // M[i] = MD[i-3] || MD[i-2] || MD[i-1]; memcpy(Mi.ptr + seed.len * 0, MDi_3.ptr, seed.len); memcpy(Mi.ptr + seed.len * 1, MDi_2.ptr, seed.len); memcpy(Mi.ptr + seed.len * 2, MDi_1.ptr, seed.len); // MDi = SHA(Mi); struct hash_context *hash = hash_alg->hash_ops->init(hash_alg, "sha", DBG_CRYPT); hash_alg->hash_ops->digest_bytes(hash, "msg", Mi.ptr, Mi.len); hash_alg->hash_ops->final_bytes(&hash, seed.ptr, seed.len); // printf("%d ", i); // print_chunk("MDi", seed, 0); } print_line(""); print_number("COUNT", j); // MDj = Seed = MD1002; // OUTPUT: MDj; (aka seed) print_chunk("MD", seed, 0); } freeanychunk(MDi_3); freeanychunk(MDi_2); freeanychunk(MDi_1); freeanychunk(Mi); print_line(""); exit(0); }
/* * Turn the raw key into SymKey. */ PK11SymKey *decode_to_key(const struct encrypt_desc *encrypt_desc, const char *encoded_key) { chunk_t raw_key = decode_to_chunk("raw_key", encoded_key); PK11SymKey *symkey = symkey_from_chunk("symkey", DBG_CRYPT, &encrypt_desc->common, raw_key); freeanychunk(raw_key); return symkey; }
static void ppk_recalc_one(PK11SymKey **sk /* updated */, PK11SymKey *ppk_key, const struct prf_desc *prf_desc, const char *name) { PK11SymKey *t = ikev2_prfplus(prf_desc, ppk_key, *sk, prf_desc->prf_key_size); release_symkey(__func__, name, sk); *sk = t; DBG(DBG_PRIVATE, { chunk_t chunk_sk = chunk_from_symkey("sk_chunk", *sk); DBG_dump_chunk(name, chunk_sk); freeanychunk(chunk_sk); });
/* * builds a pkcs7 enveloped and signed scep request */ chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg , const x509cert_t *enc_cert, int enc_alg , const x509cert_t *signer_cert, int digest_alg , const RSA_private_key_t *private_key) { chunk_t envelopedData, attributes, request; envelopedData = pkcs7_build_envelopedData(data, enc_cert, enc_alg); attributes = asn1_wrap(ASN1_SET, "mmmmm" , pkcs7_contentType_attribute() , pkcs7_messageDigest_attribute(envelopedData , digest_alg) , scep_transId_attribute(transID) , scep_messageType_attribute(msg) , scep_senderNonce_attribute()); request = pkcs7_build_signedData(envelopedData, attributes , signer_cert, digest_alg, private_key); freeanychunk(envelopedData); freeanychunk(attributes); return request; }
/* * SKEYSEED = prf(Ni | Nr, g^ir) */ PK11SymKey *ikev2_ike_sa_skeyseed(const struct prf_desc *prf_desc, const chunk_t Ni, const chunk_t Nr, PK11SymKey *dh_secret) { /* key = Ni|Nr */ chunk_t key = concat_chunk_chunk("key = Ni|Nr", Ni, Nr); struct crypt_prf *prf = crypt_prf_init_chunk("ike sa SKEYSEED", DBG_CRYPT, prf_desc, "Ni|Nr", key); freeanychunk(key); /* seed = g^ir */ crypt_prf_update_symkey("g^ir", prf, dh_secret); /* generate */ return crypt_prf_final(prf); }
static void msg_run(void) { print_number("Len", len); /* byte aligned */ passert(len == (len & -4)); /* when len==0, msg may contain one byte :-/ */ passert((len == 0 && msg.len <= 1) || (len == msg.len * BITS_PER_BYTE)); print_chunk("Msg", msg, 0); struct hash_context *hash = hash_alg->hash_ops->init(hash_alg, "sha", DBG_CRYPT); /* See above, use LEN, not MSG.LEN */ hash_alg->hash_ops->digest_bytes(hash, "msg", msg.ptr, len / BITS_PER_BYTE); chunk_t bytes = alloc_chunk(l, "bytes"); hash_alg->hash_ops->final_bytes(&hash, bytes.ptr, bytes.len); print_chunk("MD", bytes, 0); freeanychunk(bytes); }
/* * Process KE values. */ void unpack_KE_from_helper( struct state *st, const struct pluto_crypto_req *r, chunk_t *g) { const struct pcr_kenonce *kn = &r->pcr_d.kn; /* ??? if st->st_sec_in_use how could we do our job? */ passert(!st->st_sec_in_use); st->st_sec_in_use = TRUE; freeanychunk(*g); /* happens in odd error cases */ clonetochunk(*g, WIRE_CHUNK_PTR(*kn, gi), kn->gi.len, "saved gi value"); DBG(DBG_CRYPT, DBG_log("saving DH priv (local secret) and pub key into state struct")); st->st_sec_nss = kn->secret; st->st_pubk_nss = kn->pubk; }
void calc_ke(struct pluto_crypto_req *r) { MP_INT mp_g; MP_INT secret; chunk_t gi; struct pcr_kenonce *kn = &r->pcr_d.kn; const struct oakley_group_desc *group; group = lookup_group(kn->oakley_group); pluto_crypto_allocchunk(&kn->thespace , &kn->secret , LOCALSECRETSIZE); get_rnd_bytes(wire_chunk_ptr(kn, &(kn->secret)), LOCALSECRETSIZE); n_to_mpz(&secret, wire_chunk_ptr(kn, &(kn->secret)), LOCALSECRETSIZE); mpz_init(&mp_g); oswcrypto.mod_exp(&mp_g, group->generator, &secret, group->modulus); gi = mpz_to_n(&mp_g, group->bytes); pluto_crypto_allocchunk(&kn->thespace, &kn->gi, gi.len); { char *gip = wire_chunk_ptr(kn, &(kn->gi)); memcpy(gip, gi.ptr, gi.len); } DBG(DBG_CRYPT, DBG_dump("Local DH secret:\n" , wire_chunk_ptr(kn, &(kn->secret)) , LOCALSECRETSIZE); DBG_dump_chunk("Public DH value sent:\n", gi)); /* clean up after ourselves */ mpz_clear(&mp_g); mpz_clear(&secret); freeanychunk(gi); }
void free_id_content(struct id *id) { switch (id->kind) { case ID_FQDN: case ID_USER_FQDN: case ID_DER_ASN1_DN: case ID_KEY_ID: freeanychunk(id->name); break; case ID_MYID: case ID_FROMCERT: case ID_NONE: case ID_IPV4_ADDR: case ID_IPV6_ADDR: break; default: bad_case(id->kind); } }
static void gcm_run_test(void) { print_number("Count", NULL, count); print_symkey("Key", NULL, key, 0); print_chunk("IV", NULL, iv, 0); print_chunk("CT", NULL, ct, 0); print_chunk("AAD", NULL, aad, 0); print_chunk("Tag", NULL, tag, 0); const struct encrypt_desc *gcm_alg = lookup_by_taglen(); if (gcm_alg == NULL) { fprintf(stderr, "taglen %lu not supported\n", taglen); return; } PK11SymKey *gcm_key = encrypt_key_from_symkey_bytes("GCM key", gcm_alg, 0, sizeof_symkey(key), key); chunk_t text_and_tag = clone_chunk_chunk(ct, tag, "text-and-tag"); bool result = gcm_alg->encrypt_ops ->do_aead(gcm_alg, salt.ptr, salt.len, iv.ptr, iv.len, aad.ptr, aad.len, text_and_tag.ptr, ct.len, tag.len, gcm_key, FALSE/*encrypt*/); if (result) { /* plain text */ chunk_t pt = { .ptr = text_and_tag.ptr, .len = ct.len, }; print_chunk("PT", NULL, pt, 0); } else { print_line("FAIL"); } release_symkey(__func__, "GCM-key", &gcm_key); freeanychunk(text_and_tag); }
/* * Processing FOR KE values. */ void unpack_KE(struct state *st , struct pluto_crypto_req *r , chunk_t *g) { struct pcr_kenonce *kn = &r->pcr_d.kn; if (!st->st_sec_in_use) { st->st_sec_in_use = TRUE; freeanychunk(*g); /* happens in odd error cases */ clonetochunk(*g, wire_chunk_ptr(kn, &(kn->gi)) , kn->gi.len, "saved gi value"); n_to_mpz(&st->st_sec , wire_chunk_ptr(kn, &(kn->secret)) , kn->secret.len); clonetochunk(st->st_sec_chunk , wire_chunk_ptr(kn, &(kn->secret)) , kn->secret.len, "long term secret"); } }
stf_status ikev2_calc_no_ppk_auth(struct state *st, unsigned char *id_hash, chunk_t *no_ppk_auth /* output */) { struct connection *c = st->st_connection; enum keyword_authby authby = c->spd.this.authby; freeanychunk(*no_ppk_auth); /* in case it was occupied */ switch (authby) { case AUTH_RSASIG: { const struct asn1_hash_blob *h = NULL; if (st->st_hash_negotiated & NEGOTIATE_AUTH_HASH_SHA2_512) { h = &asn1_rsa_pss_sha2_512; } else if (st->st_hash_negotiated & NEGOTIATE_AUTH_HASH_SHA2_384) { h = &asn1_rsa_pss_sha2_384; } else if (st->st_hash_negotiated & NEGOTIATE_AUTH_HASH_SHA2_256) { h = &asn1_rsa_pss_sha2_256; } else if (c->sighash_policy & POL_SIGHASH_NONE) { /* RSA with SHA1 without Digsig: no oid blob appended */ if (!ikev2_calculate_rsa_hash(st, st->st_original_role, id_hash, NULL, no_ppk_auth, IKEv2_AUTH_HASH_SHA1)) { /* ??? what diagnostic? */ return STF_FAIL; } return STF_OK; } else { loglog(RC_LOG_SERIOUS, "No compatible hash algo"); return STF_FAIL; } chunk_t hashval; if (!ikev2_calculate_rsa_hash(st, st->st_original_role, id_hash, NULL, &hashval, h->hash_algo)) { /* ??? what diagnostic? */ return STF_FAIL; } if (st->st_seen_hashnotify) { /* * combine blobs to create no_ppk_auth: * - ASN.1 algo blob * - hashval */ int len = h->blob_sz + hashval.len; u_char *blobs = alloc_bytes(len, "bytes for blobs for AUTH_DIGSIG NO_PPK_AUTH"); memcpy(&blobs[0], h->blob, h->blob_sz); memcpy(&blobs[h->blob_sz], hashval.ptr, hashval.len); freeanychunk(hashval); setchunk(*no_ppk_auth, blobs, len); } return STF_OK; } case AUTH_PSK: /* store in no_ppk_auth */ if (!ikev2_create_psk_auth(AUTH_PSK, st, id_hash, no_ppk_auth)) { /* ??? what diagnostic? */ return STF_INTERNAL_ERROR; } return STF_OK; default: bad_case(authby); } }
static bool test_gcm_vector(const struct encrypt_desc *encrypt_desc, const struct gcm_test_vector *test) { DBG(DBG_CRYPT, DBG_log("test_gcm_vector: enter")); const size_t salt_size = encrypt_desc->salt_size; bool ok = TRUE; PK11SymKey *sym_key = decode_to_key(encrypt_desc, test->key); chunk_t salted_iv = decode_to_chunk("salted IV", test->salted_iv); passert(salted_iv.len == encrypt_desc->wire_iv_size + salt_size); chunk_t salt = { .ptr = salted_iv.ptr, .len = salt_size }; chunk_t wire_iv = { .ptr = salted_iv.ptr + salt_size, .len = salted_iv.len - salt_size }; chunk_t aad = decode_to_chunk("AAD", test->aad); chunk_t plaintext = decode_to_chunk("plaintext", test->plaintext); chunk_t ciphertext = decode_to_chunk("ciphertext", test->ciphertext); passert(plaintext.len == ciphertext.len); size_t len = plaintext.len; chunk_t tag = decode_to_chunk("tag", test->tag); chunk_t text_and_tag; text_and_tag.len = len + tag.len; text_and_tag.ptr = alloc_bytes(text_and_tag.len, "GCM data"); /* macro to test encryption or decryption * * This would be better as a function but it uses too many locals * from test_gcm_vector to be pleasant: * text_and_tag, len, tag, aad, salt, wire_iv, sym_key */ # define try(enc, desc, from, to) { \ memcpy(text_and_tag.ptr, from.ptr, from.len); \ text_and_tag.len = len + tag.len; \ DBG(DBG_CRYPT, \ DBG_log("test_gcm_vector: %s: aad-size=%zd salt-size=%zd wire-IV-size=%zd text-size=%zd tag-size=%zd", \ desc, aad.len, salt.len, wire_iv.len, len, tag.len); \ DBG_dump_chunk("test_gcm_vector: text+tag on call", \ text_and_tag)); \ if (!encrypt_desc->encrypt_ops->do_aead(encrypt_desc, \ salt.ptr, salt.len, \ wire_iv.ptr, wire_iv.len, \ aad.ptr, aad.len, \ text_and_tag.ptr, \ len, tag.len, \ sym_key, enc) || \ !verify_chunk_data("output ciphertext", \ to, text_and_tag.ptr) || \ !verify_chunk_data("TAG", tag, text_and_tag.ptr + len)) \ ok = FALSE; \ DBG(DBG_CRYPT, DBG_dump_chunk("test_gcm_vector: text+tag on return", \ text_and_tag)); \ } /* test decryption */ memcpy(text_and_tag.ptr + len, tag.ptr, tag.len); try(FALSE, "decrypt", ciphertext, plaintext); /* test encryption */ memset(text_and_tag.ptr + len, '\0', tag.len); try(TRUE, "encrypt", plaintext, ciphertext); # undef try freeanychunk(salted_iv); freeanychunk(aad); freeanychunk(plaintext); freeanychunk(ciphertext); freeanychunk(tag); freeanychunk(text_and_tag); /* Clean up. */ release_symkey(__func__, "sym_key", &sym_key); DBG(DBG_CRYPT, DBG_log("test_gcm_vector: %s", ok ? "passed" : "failed")); return ok; } bool test_gcm_vectors(const struct encrypt_desc *encrypt_desc, const struct gcm_test_vector *tests) { bool ok = TRUE; const struct gcm_test_vector *test; for (test = tests; test->key != NULL; test++) { if (!test_gcm_vector(encrypt_desc, test)) { ok = FALSE; } } return ok; }
void hmac_init(struct hmac_ctx *ctx, const struct hash_desc *h, const u_char *key, size_t key_len) { ctx->h = h; ctx->hmac_digest_len = h->hash_digest_len; /* DBG(DBG_CRYPT, DBG_log("NSS: hmac init")); */ SECStatus status; PK11SymKey *symkey = NULL, *tkey1 = NULL; /* PK11SymKey *tkey1=NULL; */ unsigned int klen; chunk_t hmac_opad, hmac_ipad, hmac_pad; memcpy(&symkey, key, key_len); klen = PK11_GetKeyLength(symkey); hmac_opad = hmac_pads(HMAC_OPAD, h->hash_block_size); hmac_ipad = hmac_pads(HMAC_IPAD, h->hash_block_size); hmac_pad = hmac_pads(0x00, h->hash_block_size - klen); if (klen > h->hash_block_size) { tkey1 = PK11_Derive_lsw(symkey, nss_key_derivation_mech( h), NULL, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, 0); } else { tkey1 = symkey; } PK11SymKey *tkey2 = pk11_derive_wrapper_lsw(tkey1, CKM_CONCATENATE_BASE_AND_DATA, hmac_pad, CKM_XOR_BASE_AND_DATA, CKA_DERIVE, h->hash_block_size); PR_ASSERT(tkey2 != NULL); ctx->ikey = pk11_derive_wrapper_lsw(tkey2, CKM_XOR_BASE_AND_DATA, hmac_ipad, nss_hash_mech( h), CKA_DIGEST, 0); PR_ASSERT(ctx->ikey != NULL); ctx->okey = pk11_derive_wrapper_lsw(tkey2, CKM_XOR_BASE_AND_DATA, hmac_opad, nss_hash_mech( h), CKA_DIGEST, 0); PR_ASSERT(ctx->okey != NULL); if (tkey1 != symkey) PK11_FreeSymKey(tkey1); PK11_FreeSymKey(tkey2); freeanychunk(hmac_opad); freeanychunk(hmac_ipad); freeanychunk(hmac_pad); ctx->ctx_nss = PK11_CreateDigestContext(nss_hash_oid(h)); PR_ASSERT(ctx->ctx_nss != NULL); status = PK11_DigestBegin(ctx->ctx_nss); PR_ASSERT(status == SECSuccess); status = PK11_DigestKey(ctx->ctx_nss, ctx->ikey); PR_ASSERT(status == SECSuccess); }
int main(int argc, char *argv[]) { bool recalculate = FALSE; int len; err_t e; err_t err = NULL; char *infile; char *conn_name; int lineno=0; struct connection *c1 = NULL; struct id moon, cassidy; struct adns_continuation *cr1 = NULL; #ifdef HAVE_EFENCE EF_PROTECT_FREE=1; #endif initproctitle(argc, argv); progname = argv[0]; leak_detective = 1; if(argc != 3 && argc!=4) { fprintf(stderr, "Usage: %s [-r] <whackrecord> <conn-name>\n", progname); exit(10); } /* skip argv0 */ argc--; argv++; if(strcmp(argv[0], "-r")==0) { recalculate = 1; /* do all crypto */ argc--; argv++; } tool_init_log(); cur_debugging |= DBG_DNS; init_adns(); { int r; struct sigaction act; act.sa_handler = &childhandler; act.sa_flags = SA_RESTART; r = sigaction(SIGCHLD, &act, NULL); passert(r == 0); } reset_globals(); /* setup a query */ cr1 = alloc_thing(struct adns_continuation, "moon lookup"); moon.kind = ID_FQDN; strtochunk(moon.name, "moon.testing.openswan.org", "dns name"); e = start_adns_query(&moon, NULL, ns_t_key, moon_continue, cr1); freeanychunk(moon.name); process_dns_results(); #if 0 cr1 = alloc_thing(struct adns_continuation, "cassidy lookup"); cassidy.kind = ID_FQDN; strtochunk(cassidy.name, "cassidy.sandelman.ca", "dns name 2"); e = start_adns_query(&cassidy, NULL, ns_t_key, cassidy_continue, cr1); freeanychunk(cassidy.name); process_dns_results(); #endif /* re-use cassidy */ cr1 = alloc_thing(struct adns_continuation, "cassidy A lookup"); e = start_adns_hostname(AF_UNSPEC, "cassidy.sandelman.ca", cassidy_host_continue, cr1); process_dns_results(); stop_adns(); report_leaks(); tool_close_log(); exit(0); }
struct private_key_stuff *lsw_nss_foreach_private_key_stuff(secret_eval func, void *uservoid, lsw_nss_buf_t err) { /* * So test for error with "if (err[0]) ..." works. */ err[0] = '\0'; PK11SlotInfo *slot = lsw_nss_get_authenticated_slot(err); if (slot == NULL) { return NULL; } SECKEYPrivateKeyList *list = PK11_ListPrivateKeysInSlot(slot); if (list == NULL) { snprintf(err, sizeof(lsw_nss_buf_t), "no list"); PK11_FreeSlot(slot); return NULL; } int line = 1; struct private_key_stuff *result = NULL; SECKEYPrivateKeyListNode *node; for (node = PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); node = PRIVKEY_LIST_NEXT(node)) { if (SECKEY_GetPrivateKeyType(node->key) != rsaKey) { /* only rsa for now */ continue; } struct private_key_stuff pks = { .kind = PPK_RSA, .on_heap = TRUE, }; { SECItem *nss_ckaid = PK11_GetLowLevelKeyIDForPrivateKey(node->key); if (nss_ckaid == NULL) { // fprintf(stderr, "ckaid not found\n"); continue; } const char *err = form_ckaid_nss(nss_ckaid, &pks.u.RSA_private_key.pub.ckaid); SECITEM_FreeItem(nss_ckaid, PR_TRUE); if (err) { // fprintf(stderr, "ckaid not found\n"); continue; } } { SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(node->key); if (pubkey != NULL) { fill_RSA_public_key(&pks.u.RSA_private_key.pub, pubkey); SECKEY_DestroyPublicKey(pubkey); } } /* * Only count private keys that get processed. */ pks.line = line++; int ret = func(NULL, &pks, uservoid); if (ret == 0) { /* * save/return the result. * * XXX: Potential Memory leak. * * lsw_foreach_secret() + lsw_get_pks() * returns an object that must not be freed * BUT lsw_nss_foreach_private_key_stuff() * returns an object that must be freed. * * For moment ignore this - as only caller is * showhostkey.c which quickly exits. */ result = clone_thing(pks, "pks"); break; } freeanyckaid(&pks.u.RSA_private_key.pub.ckaid); freeanychunk(pks.u.RSA_private_key.pub.e); freeanychunk(pks.u.RSA_private_key.pub.n); if (ret < 0) { break; } } SECKEY_DestroyPrivateKeyList(list); PK11_FreeSlot(slot); return result; }
/* MUST BE THREAD-SAFE */ static PK11SymKey *calc_dh_shared(const chunk_t g, /* converted to SECItem */ /*const*/ SECKEYPrivateKey *privk, /* NSS doesn't do const */ const struct oakley_group_desc *group, const SECKEYPublicKey *local_pubk) { struct timeval tv0; SECKEYPublicKey *remote_pubk; SECItem nss_g; PK11SymKey *dhshared; PRArenaPool *arena; SECStatus status; unsigned int dhshared_len; DBG(DBG_CRYPT, DBG_log("Started DH shared-secret computation in NSS:")); gettimeofday(&tv0, NULL); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); passert(arena != NULL); remote_pubk = (SECKEYPublicKey *) PORT_ArenaZAlloc(arena, sizeof(SECKEYPublicKey)); remote_pubk->arena = arena; remote_pubk->keyType = dhKey; remote_pubk->pkcs11Slot = NULL; remote_pubk->pkcs11ID = CK_INVALID_HANDLE; nss_g.data = g.ptr; nss_g.len = (unsigned int)g.len; nss_g.type = siBuffer; status = SECITEM_CopyItem(remote_pubk->arena, &remote_pubk->u.dh.prime, &local_pubk->u.dh.prime); passert(status == SECSuccess); status = SECITEM_CopyItem(remote_pubk->arena, &remote_pubk->u.dh.base, &local_pubk->u.dh.base); passert(status == SECSuccess); status = SECITEM_CopyItem(remote_pubk->arena, &remote_pubk->u.dh.publicValue, &nss_g); passert(status == SECSuccess); dhshared = PK11_PubDerive(privk, remote_pubk, PR_FALSE, NULL, NULL, CKM_DH_PKCS_DERIVE, CKM_CONCATENATE_DATA_AND_BASE, CKA_DERIVE, group->bytes, lsw_return_nss_password_file_info()); passert(dhshared != NULL); dhshared_len = PK11_GetKeyLength(dhshared); if (group->bytes > dhshared_len) { DBG(DBG_CRYPT, DBG_log("Dropped %lu leading zeros", group->bytes - dhshared_len)); chunk_t zeros; PK11SymKey *newdhshared; CK_KEY_DERIVATION_STRING_DATA string_params; SECItem params; zeros = hmac_pads(0x00, group->bytes - dhshared_len); params.data = (unsigned char *)&string_params; params.len = sizeof(string_params); string_params.pData = zeros.ptr; string_params.ulLen = zeros.len; newdhshared = PK11_Derive(dhshared, CKM_CONCATENATE_DATA_AND_BASE, ¶ms, CKM_CONCATENATE_DATA_AND_BASE, CKA_DERIVE, 0); passert(newdhshared != NULL); PK11_FreeSymKey(dhshared); dhshared = newdhshared; freeanychunk(zeros); } else { DBG(DBG_CRYPT, DBG_log("Dropped no leading zeros %d", dhshared_len)); } /* nss_symkey_log(dhshared, "dhshared"); */ DBG(DBG_CRYPT, { struct timeval tv1; unsigned long tv_diff; gettimeofday(&tv1, NULL); tv_diff = (tv1.tv_sec - tv0.tv_sec) * 1000000 + (tv1.tv_usec - tv0.tv_usec); DBG_log("calc_dh_shared(): time elapsed (%s): %ld usec", enum_show(&oakley_group_names, group->group), tv_diff); });
void hmac_init(struct hmac_ctx *ctx, const struct hash_desc *h, const u_char *key, size_t key_len) { #ifndef HAVE_LIBNSS int k; #endif ctx->h = h; ctx->hmac_digest_len = h->hash_digest_len; #ifdef HAVE_LIBNSS /* DBG(DBG_CRYPT, DBG_log("NSS: hmac init")); */ SECStatus status; PK11SymKey *symkey=NULL, *tkey1=NULL; /* PK11SymKey *tkey1=NULL; */ unsigned int klen; chunk_t hmac_opad, hmac_ipad, hmac_pad; memcpy(&symkey, key, key_len); klen = PK11_GetKeyLength(symkey); hmac_opad = hmac_pads(HMAC_OPAD,HMAC_BUFSIZE); hmac_ipad = hmac_pads(HMAC_IPAD,HMAC_BUFSIZE); hmac_pad = hmac_pads(0x00,HMAC_BUFSIZE-klen); if(klen > HMAC_BUFSIZE) { tkey1 = PK11_Derive_osw(symkey, nss_key_derivation_mech(h) , NULL, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, 0); } else { tkey1 = symkey; } PK11SymKey *tkey2 = pk11_derive_wrapper_osw(tkey1, CKM_CONCATENATE_BASE_AND_DATA , hmac_pad,CKM_XOR_BASE_AND_DATA, CKA_DERIVE, HMAC_BUFSIZE); PR_ASSERT(tkey2!=NULL); ctx->ikey = pk11_derive_wrapper_osw(tkey2, CKM_XOR_BASE_AND_DATA , hmac_ipad,nss_hash_mech(h), CKA_DIGEST, 0); PR_ASSERT(ctx->ikey !=NULL); ctx->okey = pk11_derive_wrapper_osw(tkey2, CKM_XOR_BASE_AND_DATA , hmac_opad,nss_hash_mech(h), CKA_DIGEST, 0); PR_ASSERT(ctx->okey !=NULL); if(tkey1!=symkey) { PK11_FreeSymKey(tkey1); } PK11_FreeSymKey(tkey2); freeanychunk(hmac_opad); freeanychunk(hmac_ipad); freeanychunk(hmac_pad); ctx->ctx_nss = PK11_CreateDigestContext(nss_hash_oid(h)); PR_ASSERT(ctx->ctx_nss!=NULL); status=PK11_DigestBegin(ctx->ctx_nss); PR_ASSERT(status==SECSuccess); status=PK11_DigestKey(ctx->ctx_nss, ctx->ikey); PR_ASSERT(status==SECSuccess); #else /* Prepare the two pads for the HMAC */ memset(ctx->buf1, '\0', HMAC_BUFSIZE); if (key_len <= HMAC_BUFSIZE) { memcpy(ctx->buf1, key, key_len); } else { h->hash_init(&ctx->hash_ctx); h->hash_update(&ctx->hash_ctx, key, key_len); h->hash_final(ctx->buf1, &ctx->hash_ctx); } memcpy(ctx->buf2, ctx->buf1, HMAC_BUFSIZE); for (k = 0; k < HMAC_BUFSIZE; k++) { ctx->buf1[k] ^= HMAC_IPAD; ctx->buf2[k] ^= HMAC_OPAD; } hmac_reinit(ctx); #endif }
static bool ike_alg_nss_gcm(const struct encrypt_desc *alg, u_int8_t *salt, size_t salt_size, u_int8_t *wire_iv, size_t wire_iv_size, u_int8_t *aad, size_t aad_size, u_int8_t *text_and_tag, size_t text_size, size_t tag_size, PK11SymKey *sym_key, bool enc) { /* See pk11gcmtest.c */ bool ok = TRUE; chunk_t salt_chunk = { .ptr = salt, .len = salt_size, }; chunk_t wire_iv_chunk = { .ptr = wire_iv, .len = wire_iv_size, }; chunk_t iv = concat_chunk_chunk("IV", salt_chunk, wire_iv_chunk); CK_GCM_PARAMS gcm_params; gcm_params.pIv = iv.ptr; gcm_params.ulIvLen = iv.len; gcm_params.pAAD = aad; gcm_params.ulAADLen = aad_size; gcm_params.ulTagBits = tag_size * 8; SECItem param; param.type = siBuffer; param.data = (void*)&gcm_params; param.len = sizeof gcm_params; /* Output buffer for transformed data. */ size_t text_and_tag_size = text_size + tag_size; u_int8_t *out_buf = PR_Malloc(text_and_tag_size); unsigned int out_len = 0; if (enc) { SECStatus rv = PK11_Encrypt(sym_key, alg->common.nss_mechanism, ¶m, out_buf, &out_len, text_and_tag_size, text_and_tag, text_size); if (rv != SECSuccess) { loglog(RC_LOG_SERIOUS, "do_aes_gcm: PK11_Encrypt failure (err %d)", PR_GetError()); ok = FALSE; } else if (out_len != text_and_tag_size) { loglog(RC_LOG_SERIOUS, "do_aes_gcm: PK11_Encrypt output length of %u not the expected %zd", out_len, text_and_tag_size); ok = FALSE; } } else { SECStatus rv = PK11_Decrypt(sym_key, CKM_AES_GCM, ¶m, out_buf, &out_len, text_and_tag_size, text_and_tag, text_and_tag_size); if (rv != SECSuccess) { loglog(RC_LOG_SERIOUS, "do_aes_gcm: PK11_Decrypt failure (err %d)", PR_GetError()); ok = FALSE; } else if (out_len != text_size) { loglog(RC_LOG_SERIOUS, "do_aes_gcm: PK11_Decrypt output length of %u not the expected %zd", out_len, text_size); ok = FALSE; } } memcpy(text_and_tag, out_buf, out_len); PR_Free(out_buf); freeanychunk(iv); return ok; }
/* here we are just freeing RAM */ void free_state(struct state *st) { delete_event(st); /* delete any pending timer event */ { struct msgid_list *p = st->st_used_msgids; while (p != NULL) { struct msgid_list *q = p; p = p->next; pfree(q); } } unreference_key(&st->st_peer_pubkey); free_sa(st->st_sadb); st->st_sadb=NULL; if (st->st_sec_in_use) { #ifdef HAVE_LIBNSS SECKEYPrivateKey *privk; SECKEYPublicKey *pubk; memcpy(&pubk,st->pubk.ptr,st->pubk.len); SECKEY_DestroyPublicKey(pubk); freeanychunk(st->pubk); memcpy(&privk,st->st_sec_chunk.ptr,st->st_sec_chunk.len); SECKEY_DestroyPrivateKey(privk); #else mpz_clear(&(st->st_sec)); #endif pfreeany(st->st_sec_chunk.ptr); } freeanychunk(st->st_firstpacket_me); freeanychunk(st->st_firstpacket_him); freeanychunk(st->st_tpacket); freeanychunk(st->st_rpacket); freeanychunk(st->st_p1isa); freeanychunk(st->st_gi); freeanychunk(st->st_gr); freeanychunk(st->st_shared); freeanychunk(st->st_ni); freeanychunk(st->st_nr); #ifdef HAVE_LIBNSS free_osw_nss_symkey(st->st_skeyid); free_osw_nss_symkey(st->st_skey_d); free_osw_nss_symkey(st->st_skey_ai); free_osw_nss_symkey(st->st_skey_ar); free_osw_nss_symkey(st->st_skey_ei); free_osw_nss_symkey(st->st_skey_er); free_osw_nss_symkey(st->st_skey_pi); free_osw_nss_symkey(st->st_skey_pr); free_osw_nss_symkey(st->st_enc_key); if(st->st_ah.our_keymat!=NULL) memset(st->st_ah.our_keymat, 0, st->st_ah.keymat_len); if(st->st_ah.peer_keymat!=NULL) memset(st->st_ah.peer_keymat, 0, st->st_ah.keymat_len); if(st->st_esp.our_keymat!=NULL) memset(st->st_esp.our_keymat, 0, st->st_esp.keymat_len); if(st->st_esp.peer_keymat!=NULL) memset(st->st_esp.peer_keymat, 0, st->st_esp.keymat_len); #endif freeanychunk(st->st_skeyid); freeanychunk(st->st_skey_d); freeanychunk(st->st_skey_ai); freeanychunk(st->st_skey_ar); freeanychunk(st->st_skey_ei); freeanychunk(st->st_skey_er); freeanychunk(st->st_skey_pi); freeanychunk(st->st_skey_pr); freeanychunk(st->st_enc_key); pfreeany(st->st_ah.our_keymat); pfreeany(st->st_ah.peer_keymat); pfreeany(st->st_esp.our_keymat); pfreeany(st->st_esp.peer_keymat); freeanychunk(st->st_xauth_password); #ifdef HAVE_LABELED_IPSEC pfreeany(st->sec_ctx); #endif pfree(st); }
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); }