Path: blob/main/crypto/heimdal/lib/krb5/crypto-pk.c
34890 views
/*1* Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan2* (Royal Institute of Technology, Stockholm, Sweden).3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8*9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11*12* 2. Redistributions in binary form must reproduce the above copyright13* notice, this list of conditions and the following disclaimer in the14* documentation and/or other materials provided with the distribution.15*16* 3. Neither the name of the Institute nor the names of its contributors17* may be used to endorse or promote products derived from this software18* without specific prior written permission.19*20* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND21* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE22* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE23* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE24* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL25* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS26* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)27* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT28* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY29* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF30* SUCH DAMAGE.31*/3233#include "krb5_locl.h"3435#include <pkinit_asn1.h>3637krb5_error_code38_krb5_pk_octetstring2key(krb5_context context,39krb5_enctype type,40const void *dhdata,41size_t dhsize,42const heim_octet_string *c_n,43const heim_octet_string *k_n,44krb5_keyblock *key)45{46struct _krb5_encryption_type *et = _krb5_find_enctype(type);47krb5_error_code ret;48size_t keylen, offset;49void *keydata;50unsigned char counter;51unsigned char shaoutput[SHA_DIGEST_LENGTH];52EVP_MD_CTX *m;5354if(et == NULL) {55krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,56N_("encryption type %d not supported", ""),57type);58return KRB5_PROG_ETYPE_NOSUPP;59}60keylen = (et->keytype->bits + 7) / 8;6162keydata = malloc(keylen);63if (keydata == NULL) {64krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));65return ENOMEM;66}6768m = EVP_MD_CTX_create();69if (m == NULL) {70free(keydata);71krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));72return ENOMEM;73}7475counter = 0;76offset = 0;77do {7879EVP_DigestInit_ex(m, EVP_sha1(), NULL);80EVP_DigestUpdate(m, &counter, 1);81EVP_DigestUpdate(m, dhdata, dhsize);8283if (c_n)84EVP_DigestUpdate(m, c_n->data, c_n->length);85if (k_n)86EVP_DigestUpdate(m, k_n->data, k_n->length);8788EVP_DigestFinal_ex(m, shaoutput, NULL);8990memcpy((unsigned char *)keydata + offset,91shaoutput,92min(keylen - offset, sizeof(shaoutput)));9394offset += sizeof(shaoutput);95counter++;96} while(offset < keylen);97memset(shaoutput, 0, sizeof(shaoutput));9899EVP_MD_CTX_destroy(m);100101ret = krb5_random_to_key(context, type, keydata, keylen, key);102memset(keydata, 0, sizeof(keylen));103free(keydata);104return ret;105}106107static krb5_error_code108encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data)109{110KRB5PrincipalName pn;111krb5_error_code ret;112size_t size = 0;113114pn.principalName = p->name;115pn.realm = p->realm;116117ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length,118&pn, &size, ret);119if (ret) {120krb5_data_zero(data);121krb5_set_error_message(context, ret,122N_("Failed to encode KRB5PrincipalName", ""));123return ret;124}125if (data->length != size)126krb5_abortx(context, "asn1 compiler internal error");127return 0;128}129130static krb5_error_code131encode_otherinfo(krb5_context context,132const AlgorithmIdentifier *ai,133krb5_const_principal client,134krb5_const_principal server,135krb5_enctype enctype,136const krb5_data *as_req,137const krb5_data *pk_as_rep,138const Ticket *ticket,139krb5_data *other)140{141PkinitSP80056AOtherInfo otherinfo;142PkinitSuppPubInfo pubinfo;143krb5_error_code ret;144krb5_data pub;145size_t size = 0;146147krb5_data_zero(other);148memset(&otherinfo, 0, sizeof(otherinfo));149memset(&pubinfo, 0, sizeof(pubinfo));150151pubinfo.enctype = enctype;152pubinfo.as_REQ = *as_req;153pubinfo.pk_as_rep = *pk_as_rep;154pubinfo.ticket = *ticket;155ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length,156&pubinfo, &size, ret);157if (ret) {158krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));159return ret;160}161if (pub.length != size)162krb5_abortx(context, "asn1 compiler internal error");163164ret = encode_uvinfo(context, client, &otherinfo.partyUInfo);165if (ret) {166free(pub.data);167return ret;168}169ret = encode_uvinfo(context, server, &otherinfo.partyVInfo);170if (ret) {171free(otherinfo.partyUInfo.data);172free(pub.data);173return ret;174}175176otherinfo.algorithmID = *ai;177otherinfo.suppPubInfo = &pub;178179ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length,180&otherinfo, &size, ret);181free(otherinfo.partyUInfo.data);182free(otherinfo.partyVInfo.data);183free(pub.data);184if (ret) {185krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));186return ret;187}188if (other->length != size)189krb5_abortx(context, "asn1 compiler internal error");190191return 0;192}193194195196krb5_error_code197_krb5_pk_kdf(krb5_context context,198const struct AlgorithmIdentifier *ai,199const void *dhdata,200size_t dhsize,201krb5_const_principal client,202krb5_const_principal server,203krb5_enctype enctype,204const krb5_data *as_req,205const krb5_data *pk_as_rep,206const Ticket *ticket,207krb5_keyblock *key)208{209struct _krb5_encryption_type *et;210krb5_error_code ret;211krb5_data other;212size_t keylen, offset;213uint32_t counter;214unsigned char *keydata;215unsigned char shaoutput[SHA512_DIGEST_LENGTH];216const EVP_MD *md;217EVP_MD_CTX *m;218219if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) == 0) {220md = EVP_sha1();221} else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha256, &ai->algorithm) == 0) {222md = EVP_sha256();223} else if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha512, &ai->algorithm) == 0) {224md = EVP_sha512();225} else {226krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,227N_("KDF not supported", ""));228return KRB5_PROG_ETYPE_NOSUPP;229}230if (ai->parameters != NULL &&231(ai->parameters->length != 2 ||232memcmp(ai->parameters->data, "\x05\x00", 2) != 0))233{234krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,235N_("kdf params not NULL or the NULL-type",236""));237return KRB5_PROG_ETYPE_NOSUPP;238}239240et = _krb5_find_enctype(enctype);241if(et == NULL) {242krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,243N_("encryption type %d not supported", ""),244enctype);245return KRB5_PROG_ETYPE_NOSUPP;246}247keylen = (et->keytype->bits + 7) / 8;248249keydata = malloc(keylen);250if (keydata == NULL) {251krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));252return ENOMEM;253}254255ret = encode_otherinfo(context, ai, client, server,256enctype, as_req, pk_as_rep, ticket, &other);257if (ret) {258free(keydata);259return ret;260}261262m = EVP_MD_CTX_create();263if (m == NULL) {264free(keydata);265free(other.data);266krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));267return ENOMEM;268}269270offset = 0;271counter = 1;272do {273unsigned char cdata[4];274275EVP_DigestInit_ex(m, md, NULL);276_krb5_put_int(cdata, counter, 4);277EVP_DigestUpdate(m, cdata, 4);278EVP_DigestUpdate(m, dhdata, dhsize);279EVP_DigestUpdate(m, other.data, other.length);280281EVP_DigestFinal_ex(m, shaoutput, NULL);282283memcpy((unsigned char *)keydata + offset,284shaoutput,285min(keylen - offset, EVP_MD_CTX_size(m)));286287offset += EVP_MD_CTX_size(m);288counter++;289} while(offset < keylen);290memset(shaoutput, 0, sizeof(shaoutput));291292EVP_MD_CTX_destroy(m);293free(other.data);294295ret = krb5_random_to_key(context, enctype, keydata, keylen, key);296memset(keydata, 0, sizeof(keylen));297free(keydata);298299return ret;300}301302303