From f9a8ebc977ec38d40b644afd29056cdafed2d1d9 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Mon, 27 Sep 2010 18:52:32 -0400 Subject: [PATCH 001/150] - rough mostly-returns-ENOSYS NSS version --- src/plugins/preauth/pkinit/pkinit_crypto_nss.c | 1052 ++++++++++++++++++++++++ 1 files changed, 1052 insertions(+), 0 deletions(-) create mode 100644 src/plugins/preauth/pkinit/pkinit_crypto_nss.c diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c new file mode 100644 index 0000000..b7c6716 --- /dev/null +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -0,0 +1,1052 @@ +/* + * Copyright (c) 2010 Red Hat, Inc. + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of Red Hat, Inc., nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "k5-int.h" +#include "k5-int-pkinit.h" +#include "pkinit.h" +#include "pkinit_crypto.h" +#include "krb5.h" + +#include +#include +#include +#include +#include + +#define CONFIGDIR "/etc/pki/nssdb" + +/* Plugin and request state. */ +struct _pkinit_plg_crypto_context { + PLArenaPool *pool; + NSSInitContext *ncontext; +}; + +struct _pkinit_req_crypto_context { + PLArenaPool *pool; + CERTCertificate *cert; + SECKEYPrivateKey *client_seckey; +}; + +struct _pkinit_identity_crypto_context { + PLArenaPool *pool; + PK11SlotList *slots; + PK11SlotInfo *slot; + CERTCertList *certs; + CERTCertificate *cert; + krb5_prompter_fct prompter; + void *prompter_data; +}; + +struct _pkinit_cert_info { /* aka _pkinit_cert_handle */ + struct _pkinit_identity_crypto_context *id_cryptoctx; + CERTCertificate *cert; +}; + +struct _pkinit_cert_iter_info { /* aka _pkinit_cert_iter_handle */ + struct _pkinit_identity_crypto_context *id_cryptoctx; + CERTCertListNode *node; +}; + +/* Protocol elements. */ + +/* DH parameters: draft-ietf-cat-kerberos-pk-init-08.txt, 3.1.2.2. */ +struct dh_parameters { + SECItem p, g, private_value_length; +}; +static const SEC_ASN1Template +dh_parameters_template[] = { + { + .kind = SEC_ASN1_SEQUENCE, + .offset = 0, + .sub = NULL, + .size = sizeof(struct dh_parameters), + }, + { + .kind = SEC_ASN1_INTEGER, + .offset = offsetof(struct dh_parameters, p), + .sub = &SEC_IntegerTemplate, + .size = sizeof(SECItem), + }, + { + .kind = SEC_ASN1_INTEGER, + .offset = offsetof(struct dh_parameters, g), + .sub = &SEC_IntegerTemplate, + .size = sizeof(SECItem), + }, + { + .kind = SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, + .offset = offsetof(struct dh_parameters, private_value_length), + .sub = &SEC_IntegerTemplate, + .size = sizeof(SECItem), + }, + { 0, 0, NULL, 0}, +}; + +/* ValidationParms: RFC 2459, 7.3.2. */ +struct validation_parms { + SECItem seed, pgen_counter; +}; +static const SEC_ASN1Template +validation_parms_template[] = { + { + .kind = SEC_ASN1_SEQUENCE, + .offset = 0, + .sub = NULL, + .size = sizeof(struct validation_parms), + }, + { + .kind = SEC_ASN1_BIT_STRING, + .offset = offsetof(struct validation_parms, seed), + .sub = &SEC_BitStringTemplate, + .size = sizeof(SECItem), + }, + { + .kind = SEC_ASN1_INTEGER, + .offset = offsetof(struct validation_parms, pgen_counter), + .sub = &SEC_IntegerTemplate, + .size = sizeof(SECItem), + }, + { 0, 0, NULL, 0}, +}; + +/* DomainParameters: RFC 2459, 7.3.2. */ +struct domain_parameters { + SECItem p, g, q, j; + struct validation_parms *validation_parms; +}; +static const SEC_ASN1Template +domain_parameters_template[] = { + { + .kind = SEC_ASN1_SEQUENCE, + .offset = 0, + .sub = NULL, + .size = sizeof(struct domain_parameters), + }, + { + .kind = SEC_ASN1_INTEGER, + .offset = offsetof(struct domain_parameters, p), + .sub = &SEC_IntegerTemplate, + .size = sizeof(SECItem), + }, + { + .kind = SEC_ASN1_INTEGER, + .offset = offsetof(struct domain_parameters, g), + .sub = &SEC_IntegerTemplate, + .size = sizeof(SECItem), + }, + { + .kind = SEC_ASN1_INTEGER, + .offset = offsetof(struct domain_parameters, q), + .sub = &SEC_IntegerTemplate, + .size = sizeof(SECItem), + }, + { + .kind = SEC_ASN1_INTEGER | SEC_ASN1_OPTIONAL, + .offset = offsetof(struct domain_parameters, j), + .sub = &SEC_IntegerTemplate, + .size = sizeof(SECItem), + }, + { + .kind = SEC_ASN1_INLINE | + SEC_ASN1_POINTER | + SEC_ASN1_OPTIONAL, + .offset = offsetof(struct domain_parameters, validation_parms), + .sub = &validation_parms_template, + .size = sizeof(struct validation_parms *), + }, + { 0, 0, NULL, 0}, +}; + +krb5_error_code +pkinit_init_identity_crypto(pkinit_identity_crypto_context *id_cryptoctx) +{ + PLArenaPool *pool; + pool = PORT_NewArena(sizeof(double)); + if (pool != NULL) { + *id_cryptoctx = PORT_ArenaZAlloc(pool, sizeof(*id_cryptoctx)); + if (*id_cryptoctx != NULL) { + (*id_cryptoctx)->pool = pool; + (*id_cryptoctx)->certs = CERT_NewCertList(); + if ((*id_cryptoctx)->certs != NULL) { + return 0; + } + } + PORT_FreeArena(pool, PR_TRUE); + } + return ENOMEM; +} + +void +pkinit_fini_identity_crypto(pkinit_identity_crypto_context id_cryptoctx) +{ + CERT_DestroyCertList(id_cryptoctx->certs); + PORT_FreeArena(id_cryptoctx->pool, PR_TRUE); +} + +krb5_error_code +pkinit_init_plg_crypto(pkinit_plg_crypto_context *plg_cryptoctx) +{ + PLArenaPool *pool; + pool = PORT_NewArena(sizeof(double)); + if (pool != NULL) { + *plg_cryptoctx = PORT_ArenaZAlloc(pool, sizeof(*plg_cryptoctx)); + if (*plg_cryptoctx != NULL) { + (*plg_cryptoctx)->pool = pool; + (*plg_cryptoctx)->ncontext = NSS_InitContext(CONFIGDIR, + NULL, + NULL, + NULL, + NULL, + 0); + if ((*plg_cryptoctx)->ncontext != NULL) { + return 0; + } + } + PORT_FreeArena(pool, PR_TRUE); + } + return ENOMEM; +} + +void +pkinit_fini_plg_crypto(pkinit_plg_crypto_context plg_cryptoctx) +{ + NSS_ShutdownContext(plg_cryptoctx->ncontext); + PORT_FreeArena(plg_cryptoctx->pool, PR_TRUE); +} + +krb5_error_code +pkinit_init_req_crypto(pkinit_req_crypto_context *req_cryptoctx) +{ + PLArenaPool *pool; + pool = PORT_NewArena(sizeof(double)); + if (pool != NULL) { + *req_cryptoctx = PORT_ArenaZAlloc(pool, sizeof(*req_cryptoctx)); + if (*req_cryptoctx != NULL) { + (*req_cryptoctx)->pool = pool; + return 0; + } + PORT_FreeArena(pool, PR_TRUE); + } + return ENOMEM; +} + +void +pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx) +{ + if (req_cryptoctx->cert != NULL) { + CERT_DestroyCertificate(req_cryptoctx->cert); + } + if (req_cryptoctx->client_seckey != NULL) { + SECKEY_DestroyPrivateKey(req_cryptoctx->client_seckey); + } + PORT_FreeArena(req_cryptoctx->pool, PR_TRUE); +} + +/* Duplicate the memory from the SECItem into a malloc()d buffer. */ +static int +secitem_to_buf_len(SECItem *item, unsigned char **out, unsigned int *len) +{ + *out = malloc(item->len); + if (*out == NULL) { + return ENOMEM; + } + memcpy(*out, item->data, item->len); + *len = item->len; + return 0; +} + +/* Encode the raw buffer as an unsigned integer, then into a bit string. If + * the first byte in the buffer has its high bit set, we need to prepend a zero + * byte to make sure it isn't treated as a negative value. */ +static int +secitem_to_dh_pubval(SECItem *item, unsigned char **out, unsigned int *len) +{ + PLArenaPool *pool; + SECItem *uval, uinteger, bits; + int i; + + pool = PORT_NewArena(sizeof(double)); + if (pool == NULL) { + return ENOMEM; + } + + if (item->data[0] & 0x80) { + uval = SECITEM_AllocItem(pool, NULL, item->len + 1); + if (uval == NULL) { + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + uval->data[0] = '\0'; + memcpy(uval->data + 1, item->data, item->len); + } else { + uval = item; + } + + if (SEC_ASN1EncodeItem(pool, &uinteger, uval, + SEC_IntegerTemplate) != &uinteger) { + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + if (SEC_ASN1EncodeItem(pool, &bits, &uinteger, + SEC_BitStringTemplate) != &bits) { + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + i = secitem_to_buf_len(&bits, out, len); + + PORT_FreeArena(pool, PR_TRUE); + return 0; +} + +/* Decode a bitstring that contains an unsigned integer, and return just the + * bits that make up that integer. */ +static int +secitem_from_dh_pubval(PLArenaPool *pool, + unsigned char *dh_pubkey, unsigned int dh_pubkey_len, + SECItem *bits) +{ + SECItem tmp, uinteger; + tmp.data = dh_pubkey; + tmp.len = dh_pubkey_len; + if (SEC_ASN1DecodeItem(pool, &uinteger, + SEC_BitStringTemplate, &tmp) != SECSuccess) { + return ENOMEM; + } + if (SEC_ASN1DecodeItem(pool, bits, + SEC_IntegerTemplate, &uinteger) != SECSuccess) { + return ENOMEM; + } + return 0; +} + +/* Create DH parameters to be sent to the KDC. On success, dh_params should + * contain an encoded DomainParameters structure (per RFC3279), and dh_pubkey + * should contain the public value we're prepared to send to the KDC, encoded + * first as an integer and then wrapped up in a bit string. */ +krb5_error_code +client_create_dh(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int dh_size_bits, + unsigned char **dh_params, + unsigned int *dh_params_len, + unsigned char **dh_pubkey, + unsigned int *dh_pubkey_len) +{ + PLArenaPool *pool; + PK11SlotInfo *slot; + SECKEYPrivateKey *priv; + SECKEYPublicKey *pub; + SECKEYDHParams dh_param; + SECStatus status; + PQGParams *pqg_params; + PQGVerify *pqg_verify; + struct domain_parameters params; + SECItem encoded; + int pqg_size; + + pool = PORT_NewArena(sizeof(double)); + if (pool == NULL) { + return ENOMEM; + } + memset(¶ms, 0, sizeof(params)); + + /* Generate domain parameters. The size parameter we pass in will + * eventually be fed into PQG_INDEX_TO_PBITS (see blapit.h) to + * determine the number of bits. */ + pqg_size = ((dh_size_bits > 512) ? (dh_size_bits - 512) : 0) / 64; + if (PK11_PQG_ParamGen(pqg_size, &pqg_params, + &pqg_verify) != SECSuccess) { + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + if ((PK11_PQG_VerifyParams(pqg_params, pqg_verify, + &status) != SECSuccess) || + (status != SECSuccess)) { + PK11_PQG_DestroyParams(pqg_params); + PK11_PQG_DestroyVerify(pqg_verify); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + PK11_PQG_DestroyVerify(pqg_verify); + + /* Set up to generate the public key. */ + memset(&dh_param, 0, sizeof(dh_param)); + dh_param.arena = pool; + dh_param.prime = pqg_params->prime; + dh_param.base = pqg_params->base; + + /* Generate a public value and a private key. */ + slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN, NULL); + if (slot == NULL) { + PK11_PQG_DestroyParams(pqg_params); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + pub = NULL; + priv = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, + &dh_param, &pub, PR_FALSE, PR_FALSE, NULL); + + /* Finish building the return values. */ + params.p = pqg_params->prime; + params.g = pqg_params->base; + params.q = pqg_params->subPrime; + if (SEC_ASN1EncodeItem(pool, &encoded, ¶ms, + domain_parameters_template) != &encoded) { + PK11_FreeSlot(slot); + PK11_PQG_DestroyParams(pqg_params); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + /* Export the return values. */ + if (secitem_to_buf_len(&encoded, dh_params, dh_params_len) != 0) { + PK11_FreeSlot(slot); + PK11_PQG_DestroyParams(pqg_params); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + if (secitem_to_dh_pubval(&pub->u.dh.publicValue, dh_pubkey, + dh_pubkey_len) != 0) { + free(*dh_params); + *dh_params = NULL; + PK11_FreeSlot(slot); + PK11_PQG_DestroyParams(pqg_params); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + /* Save our private key for reuse later. */ + SECKEY_DestroyPublicKey(pub); + PK11_PQG_DestroyParams(pqg_params); + if (req_cryptoctx->client_seckey != NULL) { + SECKEY_DestroyPrivateKey(req_cryptoctx->client_seckey); + } + req_cryptoctx->client_seckey = priv; + + PK11_FreeSlot(slot); + PORT_FreeArena(pool, PR_TRUE); + return 0; +} + +/* Combine the KDC's public key value with our copy of the parameters and our + * secret key to generate the session key. */ +krb5_error_code +client_process_dh(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + unsigned char *dh_pubkey, + unsigned int dh_pubkey_len, + unsigned char **dh_session_key, + unsigned int *dh_session_key_len) +{ + PLArenaPool *pool; + PK11SlotInfo *slot; + SECKEYPublicKey *pub, pub2; + PK11SymKey *sym; + SECItem *bits; + + pool = PORT_NewArena(sizeof(double)); + if (pool == NULL) { + return ENOMEM; + } + + /* Rebuild the KDC's public key using our parameters and the supplied + * public value. */ + pub = SECKEY_ConvertToPublicKey(req_cryptoctx->client_seckey); + if (pub == NULL) { + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + pub2 = *pub; + if (secitem_from_dh_pubval(pool, dh_pubkey, dh_pubkey_len, + &pub2.u.dh.publicValue) != 0) { + SECKEY_DestroyPublicKey(pub); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + /* Generate the shared value. */ + slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN, NULL); + if (slot == NULL) { + SECKEY_DestroyPublicKey(pub); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + sym = PK11_PubDerive(req_cryptoctx->client_seckey, &pub2, PR_FALSE, + NULL, NULL, + CKM_DH_PKCS_DERIVE, + CKM_TLS_MASTER_KEY_DERIVE_DH, + CKA_DERIVE, + 0, + NULL); + if (sym == NULL) { + SECKEY_DestroyPublicKey(pub); + PK11_FreeSlot(slot); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + /* Export the shared value. */ + if ((PK11_ExtractKeyValue(sym) != SECSuccess) || + ((bits = PK11_GetKeyData(sym)) == NULL) || + (secitem_to_buf_len(bits, dh_session_key, dh_session_key_len) != 0)) { + PK11_FreeSymKey(sym); + SECKEY_DestroyPublicKey(pub); + PK11_FreeSlot(slot); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + PK11_FreeSymKey(sym); + SECKEY_DestroyPublicKey(pub); + PK11_FreeSlot(slot); + PORT_FreeArena(pool, PR_TRUE); + return 0; +} + +/* Verify that the client-supplied parameters include a prime of sufficient + * size. */ +krb5_error_code +server_check_dh(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_octet_data *dh_params, + int minbits) +{ + PLArenaPool *pool; + struct dh_parameters *params; + SECItem item; + + pool = PORT_NewArena(sizeof(double)); + if (pool == NULL) { + return ENOMEM; + } + + item.data = dh_params->data; + item.len = dh_params->length; + if (SEC_ASN1DecodeItem(pool, ¶ms, dh_parameters_template, + &item) != SECSuccess) { + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + if (params->p.len * 8 < (unsigned int) minbits) { + PORT_FreeArena(pool, PR_TRUE); + return KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + } + + PORT_FreeArena(pool, PR_TRUE); + return 0; +} + +/* Take apart the client-supplied SubjectPublicKeyInfo, which contains both an + * encoded DomainParameters structure (per RFC3279), and a public value, and + * generate our own private key and public value using the supplied parameters. + * Use our private key and the client's public value to derive the session key, + * and hand our public value and the session key back to our caller. */ +krb5_error_code +server_process_dh(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + unsigned char *received_pubkey, + unsigned int received_pub_len, + unsigned char **dh_pubkey, + unsigned int *dh_pubkey_len, + unsigned char **server_key, + unsigned int *server_key_len) +{ + PLArenaPool *pool; + CERTSubjectPublicKeyInfo *spki; + SECKEYPrivateKey *priv; + SECKEYPublicKey *pub, pub2; + SECKEYDHParams dh_params; + PK11SymKey *sym; + struct domain_parameters params; + SECItem item, *bits; + PK11SlotInfo *slot; + + pool = PORT_NewArena(sizeof(double)); + if (pool == NULL) { + return ENOMEM; + } + + /* Decode the client's public key. */ + item.data = received_pubkey; + item.len = received_pub_len; + spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&item); + if (spki == NULL) { + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + if (SEC_ASN1DecodeItem(pool, ¶ms, + domain_parameters_template, + &spki->algorithm.parameters) != SECSuccess) { + SECKEY_DestroySubjectPublicKeyInfo(spki); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + /* Set up DH parameters the using client-supplied domain parameters. */ + memset(&dh_params, 0, sizeof(dh_params)); + dh_params.arena = pool; + dh_params.prime = params.p; + dh_params.base = params.g; + + /* Generate a public value and a private key. */ + slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN, NULL); + if (slot == NULL) { + SECKEY_DestroySubjectPublicKeyInfo(spki); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + pub = NULL; + priv = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, + &dh_params, &pub, PR_FALSE, PR_FALSE, NULL); + if (priv == NULL) { + PK11_FreeSlot(slot); + SECKEY_DestroySubjectPublicKeyInfo(spki); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + /* Rebuild the client's public key using the client's parameters and + * public value. */ + pub2 = *pub; + if (secitem_from_dh_pubval(pool, + spki->subjectPublicKey.data, + spki->subjectPublicKey.len, + &pub2.u.dh.publicValue) != 0) { + SECKEY_DestroyPrivateKey(priv); + SECKEY_DestroyPublicKey(pub); + PK11_FreeSlot(slot); + SECKEY_DestroySubjectPublicKeyInfo(spki); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + /* Generate the shared value. */ + sym = PK11_PubDerive(priv, &pub2, PR_FALSE, + NULL, NULL, + CKM_DH_PKCS_DERIVE, + CKM_TLS_MASTER_KEY_DERIVE_DH, + CKA_DERIVE, + 0, + NULL); + if (sym == NULL) { + SECKEY_DestroyPrivateKey(priv); + SECKEY_DestroyPublicKey(pub); + PK11_FreeSlot(slot); + SECKEY_DestroySubjectPublicKeyInfo(spki); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + /* Export the shared value for our use and our public value for + * transmission back to the client. */ + *server_key = NULL; + *dh_pubkey = NULL; + if ((PK11_ExtractKeyValue(sym) != SECSuccess) || + ((bits = PK11_GetKeyData(sym)) == NULL) || + (secitem_to_buf_len(bits, server_key, server_key_len) != 0) || + (secitem_to_dh_pubval(&pub->u.dh.publicValue, + dh_pubkey, dh_pubkey_len) != 0)) { + free(*server_key); + free(*dh_pubkey); + PK11_FreeSymKey(sym); + SECKEY_DestroyPrivateKey(priv); + SECKEY_DestroyPublicKey(pub); + PK11_FreeSlot(slot); + SECKEY_DestroySubjectPublicKeyInfo(spki); + PORT_FreeArena(pool, PR_TRUE); + return ENOMEM; + } + + PK11_FreeSymKey(sym); + SECKEY_DestroyPrivateKey(priv); + SECKEY_DestroyPublicKey(pub); + PK11_FreeSlot(slot); + SECKEY_DestroySubjectPublicKeyInfo(spki); + PORT_FreeArena(pool, PR_TRUE); + return 0; +} + +krb5_error_code +create_issuerAndSerial(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + unsigned char **kdcId_buf, + unsigned int *kdcId_len) +{ + return ENOSYS; +} + +krb5_error_code +create_krb5_supportedCMSTypes(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_algorithm_identifier ***supportedCMSTypes) +{ + return ENOSYS; +} + +krb5_error_code +create_krb5_trustedCas(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int flag, + krb5_trusted_ca ***trustedCas) +{ + return ENOSYS; +} + +krb5_error_code +create_krb5_trustedCertifiers(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_external_principal_identifier ***trustedCertifiers) +{ + return ENOSYS; +} + +krb5_error_code +crypto_load_certs(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ) +{ + return ENOSYS; +} + +krb5_error_code +crypto_free_cert_info(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx) +{ + return ENOSYS; +} + +krb5_error_code +crypto_cert_get_count(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int *cert_count) +{ + return ENOSYS; +} + +krb5_error_code +crypto_cert_iteration_begin(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + pkinit_cert_iter_handle *iter_handle) +{ + return ENOSYS; +} + +krb5_error_code +crypto_cert_iteration_end(krb5_context context, + pkinit_cert_iter_handle iter_handle) +{ + return ENOSYS; +} + +krb5_error_code +crypto_cert_iteration_next(krb5_context context, + pkinit_cert_iter_handle iter_handle, + pkinit_cert_handle *cert_handle) +{ + return ENOSYS; +} + +krb5_error_code +crypto_cert_release(krb5_context context, + pkinit_cert_handle cert_handle) +{ + return ENOSYS; +} + +krb5_error_code +crypto_cert_get_matching_data(krb5_context context, + pkinit_cert_handle cert_handle, + pkinit_cert_matching_data **ret_data) +{ + return ENOSYS; +} + +krb5_error_code +crypto_cert_free_matching_data(krb5_context context, + pkinit_cert_matching_data *data) +{ + return ENOSYS; +} + +krb5_error_code +crypto_cert_select(krb5_context context, + pkinit_cert_matching_data *data) +{ + return ENOSYS; +} + +krb5_error_code +crypto_cert_select_default(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx) +{ + return ENOSYS; +} + +krb5_error_code +crypto_load_cas_and_crls(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_opts *idopts, + pkinit_identity_crypto_context id_cryptoctx, + int idtype, + int catype, + char *id) +{ + return ENOSYS; +} + +krb5_error_code +pkinit_get_kdc_cert(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal princ) +{ + return ENOSYS; +} + +krb5_error_code +pkinit_create_td_dh_parameters(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + pkinit_plg_opts *opts, + krb5_data **edata) +{ + return ENOSYS; +} + +krb5_error_code +pkinit_process_td_dh_params(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_algorithm_identifier **algId, + int *new_dh_size) +{ + return ENOSYS; +} + +krb5_error_code +pkinit_create_td_invalid_certificate(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_data **edata) +{ + return ENOSYS; +} + +krb5_error_code +pkinit_create_td_trusted_certifiers(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_data **edata) +{ + return ENOSYS; +} + +krb5_error_code +pkinit_process_td_trusted_certifiers(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_external_principal_identifier **trustedCertifiers, + int td_type) +{ + return ENOSYS; +} + +krb5_error_code +pkinit_check_kdc_pkid(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + unsigned char *pdid_buf, + unsigned int pkid_len, + int *valid_kdcPkId) +{ + return ENOSYS; +} + +krb5_error_code +pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx, + krb5_prompter_fct prompter, + void *prompter_data) +{ + id_cryptoctx->prompter = prompter; + id_cryptoctx->prompter_data = prompter_data; + return 0; +} + +krb5_error_code +pkinit_octetstring2key(krb5_context context, + krb5_enctype etype, + unsigned char *key, + unsigned int key_len, + krb5_keyblock *krb5key) +{ + return ENOSYS; +} + +krb5_error_code +crypto_retrieve_cert_sans(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_principal **pkinit_sans, + krb5_principal **upn_sans, + unsigned char ***kdc_hostname) +{ + return ENOSYS; +} + +krb5_error_code +crypto_check_cert_eku(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int checking_kdc_cert, + int allow_secondary_usage, + int *eku_valid) +{ + return ENOSYS; +} + +krb5_error_code +cms_contentinfo_create(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int cms_msg_type, + unsigned char *in_data, unsigned int in_length, + unsigned char **out_data, unsigned int *out_data_len) +{ + return ENOSYS; +} + +krb5_error_code +cms_envelopeddata_create(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_preauthtype pa_type, + int include_certchain, + unsigned char *key_pack, + unsigned int key_pack_len, + unsigned char **envel_data, + unsigned int *envel_data_len) + +{ + return ENOSYS; +} + +krb5_error_code +cms_envelopeddata_verify(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + krb5_preauthtype pa_type, + int require_crl_checking, + unsigned char *envel_data, + unsigned int envel_data_len, + unsigned char **signed_data, + unsigned int *signed_data_len) +{ + return ENOSYS; +} + +krb5_error_code +cms_signeddata_create(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int cms_msg_type, + int include_certchain, + unsigned char *payload, + unsigned int payload_len, + unsigned char **signed_data, + unsigned int *signed_data_len) +{ + return ENOSYS; +} + +krb5_error_code +cms_signeddata_verify(krb5_context context, + pkinit_plg_crypto_context plg_cryptoctx, + pkinit_req_crypto_context req_cryptoctx, + pkinit_identity_crypto_context id_cryptoctx, + int cms_msg_type, + int require_crl_checking, + unsigned char *signed_data, + unsigned int signed_data_len, + unsigned char **payload, + unsigned int *payload_len, + unsigned char **authz_data, + unsigned int *authz_data_len, + int *is_signed) +{ + return ENOSYS; +} -- 1.7.6.4