pkinit_apple_client.c [plain text]
#if APPLE_PKINIT
#include "pkinit_client.h"
#include "pkinit_asn1.h"
#include "pkinit_apple_utils.h"
#include "pkinit_cms.h"
#include <assert.h>
#include <sys/errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
krb5_error_code krb5int_pkinit_as_req_create(
krb5_context context,
krb5_timestamp kctime,
krb5_int32 cusec,
krb5_ui_4 nonce,
const krb5_checksum *cksum,
krb5_pkinit_signing_cert_t client_cert,
const krb5_data *trusted_CAs,
krb5_ui_4 num_trusted_CAs,
const krb5_data *kdc_cert,
krb5_data *as_req)
{
krb5_data auth_pack = {0};
krb5_error_code krtn;
krb5_data content_info = {0};
krb5int_algorithm_id *cms_types = NULL;
krb5_ui_4 num_cms_types = 0;
krb5_data *ca_issuer_sn = NULL;
krb5_data kdc_issuer_sn = {0};
krb5_data *kdc_issuer_sn_p = NULL;
krtn = krb5int_pkinit_get_cms_types(&cms_types, &num_cms_types);
if(krtn) {
return krtn;
}
krtn = krb5int_pkinit_auth_pack_encode(kctime, cusec, nonce, cksum,
cms_types, num_cms_types,
&auth_pack);
if(krtn) {
goto errOut;
}
krtn = krb5int_pkinit_create_cms_msg(&auth_pack,
client_cert,
NULL,
ECT_PkAuthData,
0, NULL,
&content_info);
if(krtn) {
goto errOut;
}
if(trusted_CAs) {
unsigned dex;
ca_issuer_sn = (krb5_data *)malloc(num_trusted_CAs * sizeof(krb5_data));
if(ca_issuer_sn == NULL) {
krtn = ENOMEM;
goto errOut;
}
for(dex=0; dex<num_trusted_CAs; dex++) {
krtn = krb5int_pkinit_get_issuer_serial(&trusted_CAs[dex],
&ca_issuer_sn[dex]);
if(krtn) {
goto errOut;
}
}
}
if(kdc_cert) {
krtn = krb5int_pkinit_get_issuer_serial(kdc_cert, &kdc_issuer_sn);
if(krtn) {
goto errOut;
}
kdc_issuer_sn_p = &kdc_issuer_sn;
}
krtn = krb5int_pkinit_pa_pk_as_req_encode(&content_info,
ca_issuer_sn, num_trusted_CAs,
kdc_issuer_sn_p,
as_req);
errOut:
if(cms_types) {
krb5int_pkinit_free_cms_types(cms_types, num_cms_types);
}
if(auth_pack.data) {
free(auth_pack.data);
}
if(content_info.data) {
free(content_info.data);
}
if(trusted_CAs) {
unsigned dex;
for(dex=0; dex<num_trusted_CAs; dex++) {
free(ca_issuer_sn[dex].data);
}
free(ca_issuer_sn);
}
if(kdc_cert) {
free(kdc_issuer_sn.data);
}
return krtn;
}
krb5_error_code krb5int_pkinit_as_rep_parse(
krb5_context context,
const krb5_data *as_rep,
krb5_pkinit_signing_cert_t client_cert,
krb5_keyblock *key_block,
krb5_checksum *checksum,
krb5int_cert_sig_status *cert_status,
krb5_data *signer_cert,
unsigned *num_all_certs,
krb5_data **all_certs)
{
krb5_data reply_key_pack = {0, 0, NULL};
krb5_error_code krtn;
krb5_data enc_key_pack = {0, 0, NULL};
krb5_data dh_signed_data = {0, 0, NULL};
krb5int_cms_content_type content_type;
krb5_pkinit_cert_db_t cert_db = NULL;
krb5_boolean is_signed;
krb5_boolean is_encrypted;
assert((as_rep != NULL) && (checksum != NULL) &&
(key_block != NULL) && (cert_status != NULL));
krtn = krb5int_pkinit_pa_pk_as_rep_decode(as_rep, &dh_signed_data, &enc_key_pack);
if(krtn) {
pkiCssmErr("krb5int_pkinit_pa_pk_as_rep_decode", krtn);
return krtn;
}
if(dh_signed_data.data) {
pkiDebug("krb5int_pkinit_as_rep_parse: unexpected dh_signed_data\n");
krtn = ASN1_BAD_FORMAT;
goto err_out;
}
if(enc_key_pack.data == NULL) {
pkiDebug("krb5int_pkinit_as_rep_parse: no enc_key_pack\n");
krtn = ASN1_BAD_FORMAT;
goto err_out;
}
krtn = krb5_pkinit_get_client_cert_db(NULL, client_cert, &cert_db);
if(krtn) {
pkiDebug("krb5int_pkinit_as_rep_parse: error in krb5_pkinit_get_client_cert_db\n");
goto err_out;
}
krtn = krb5int_pkinit_parse_cms_msg(&enc_key_pack, cert_db, FALSE,
&is_signed, &is_encrypted,
&reply_key_pack, &content_type,
signer_cert, cert_status, num_all_certs, all_certs);
if(krtn) {
pkiDebug("krb5int_pkinit_as_rep_parse: error decoding EnvelopedData\n");
goto err_out;
}
if(!is_encrypted || !is_signed) {
pkiDebug("krb5int_pkinit_as_rep_parse: not signed and encrypted!\n");
krtn = KRB5_PARSE_MALFORMED;
goto err_out;
}
if(content_type != ECT_PkReplyKeyKata) {
pkiDebug("replyKeyPack eContentType %d!\n", (int)content_type);
krtn = KRB5_PARSE_MALFORMED;
goto err_out;
}
krtn = krb5int_pkinit_reply_key_pack_decode(&reply_key_pack, key_block, checksum);
if(krtn) {
pkiDebug("krb5int_pkinit_as_rep_parse: error decoding ReplyKeyPack\n");
}
err_out:
if(reply_key_pack.data) {
free(reply_key_pack.data);
}
if(enc_key_pack.data) {
free(enc_key_pack.data);
}
if(dh_signed_data.data) {
free(dh_signed_data.data);
}
if(cert_db) {
krb5_pkinit_release_cert_db(cert_db);
}
return krtn;
}
#endif