pkinit_apple_client.c [plain text]
#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 pkinit_as_req_create(
krb5_timestamp ctime,
krb5_ui_4 cusec, krb5_ui_4 nonce,
const krb5_checksum *cksum,
pkinit_signing_cert_t client_cert, const krb5_data *kdc_cert, krb5_data *as_req) {
krb5_data auth_pack = {0, 0, NULL};
krb5_error_code krtn;
krb5_data content_info = {0, 0, NULL};
krb5_data issuerSerial = {0, 0, NULL};
krb5_data *isp = NULL;
krtn = pkinit_auth_pack_encode(ctime, cusec, nonce, cksum, &auth_pack);
if(krtn) {
return krtn;
}
krtn = pkinit_create_signed_data(&auth_pack, client_cert, TRUE, ECT_PkAuthData,
&content_info);
if(krtn) {
goto errOut;
}
if(kdc_cert) {
krtn = pkiGetIssuerAndSerial(kdc_cert, &issuerSerial);
if(krtn) {
goto errOut;
}
isp = &issuerSerial;
}
krtn = pkinit_pa_pk_as_req_encode(&content_info,
0, NULL, isp, NULL, as_req);
errOut:
if(auth_pack.data) {
free(auth_pack.data);
}
if(content_info.data) {
free(content_info.data);
}
return krtn;
}
krb5_error_code pkinit_as_rep_parse(
const krb5_data *as_rep,
pkinit_signing_cert_t client_cert, krb5_keyblock *key_block, krb5_ui_4 *nonce, pki_cert_sig_status *cert_status,
krb5_boolean *is_signed,
krb5_boolean *is_encrypted,
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 signed_data = {0, 0, NULL};
krb5_data enc_key_pack = {0, 0, NULL};
krb5_data dh_signed_data = {0, 0, NULL};
PKI_ContentType content_type;
krb5_boolean local_signed = FALSE;
krb5_boolean local_encrypted = FALSE;
pkinit_cert_db_t cert_db = NULL;
assert((as_rep != NULL) && (is_signed != NULL) && (is_encrypted != NULL) &&
(nonce != NULL) && (key_block != NULL) && (cert_status != NULL));
*is_signed = FALSE;
*is_encrypted = FALSE;
krtn = pkinit_pa_pk_as_rep_decode(as_rep, &dh_signed_data, &enc_key_pack);
if(krtn) {
pkiCssmErr("pkinit_pa_pk_as_rep_decode", krtn);
return krtn;
}
if(dh_signed_data.data) {
pkiDebug("pkinit_as_rep_parse: unexpected dh_signed_data\n");
krtn = ASN1_BAD_FORMAT;
goto err_out;
}
if(enc_key_pack.data == NULL) {
pkiDebug("pkinit_as_rep_parse: no enc_key_pack\n");
krtn = ASN1_BAD_FORMAT;
goto err_out;
}
krtn = pkinit_parse_content_info(&enc_key_pack, NULL,
&local_signed, &local_encrypted,
&signed_data, &content_type,
NULL, NULL, NULL, NULL);
if(krtn) {
pkiDebug("pkinit_as_rep_parse: error decoding EnvelopedData\n");
goto err_out;
}
if(local_encrypted) {
*is_encrypted = TRUE;
}
if(local_signed) {
pkiDebug("**WARNING: pkinit_as_rep_parse: first CMS parse yielded signed data!\n");
}
krtn = pkinit_get_client_cert_db(NULL, client_cert, &cert_db);
if(krtn) {
pkiDebug("pkinit_as_rep_parse: error in pkinit_get_client_cert_db\n");
goto err_out;
}
krtn = pkinit_parse_content_info(&signed_data, cert_db,
&local_signed, &local_encrypted,
&reply_key_pack, &content_type,
signer_cert, cert_status, num_all_certs, all_certs);
if(krtn) {
pkiDebug("pa_pk_as_rep_parse: error decoding SignedData\n");
goto err_out;
}
if(local_encrypted) {
pkiDebug("**WARNING: pkinit_as_rep_parse: 2nd CMS parse yielded encrypted!\n");
}
if(local_signed) {
*is_signed = TRUE;
}
krtn = pkinit_reply_key_pack_decode(&reply_key_pack, key_block, nonce);
if(krtn) {
pkiDebug("pkinit_as_rep_parse: error decoding ReplyKeyPack\n");
}
err_out:
if(reply_key_pack.data) {
free(reply_key_pack.data);
}
if(signed_data.data) {
free(signed_data.data);
}
if(enc_key_pack.data) {
free(enc_key_pack.data);
}
if(dh_signed_data.data) {
free(dh_signed_data.data);
}
if(cert_db) {
pkinit_release_cert_db(cert_db);
}
return krtn;
}
krb5_error_code pkinit_rand(
void *dst,
size_t len)
{
int fd = open("/dev/random", O_RDONLY, 0);
int rtn;
if(fd <= 0) {
return EIO;
}
rtn = read(fd, dst, len);
close(fd);
if(rtn != len) {
pkiDebug("pkinit_rand: short read\n");
return EIO;
}
return 0;
}