From: Greg Hudson Date: Thu, 26 Apr 2012 21:46:57 +0000 (+0000) Subject: Remove orphaned Apple PKINIT support X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=7150b8eab9fb4bf643dd1a7ac4f5be3ca455dfcb;p=krb5.git Remove orphaned Apple PKINIT support git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25830 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/include/pkinit_apple_utils.h b/src/include/pkinit_apple_utils.h deleted file mode 100644 index 77ed9a0d9..000000000 --- a/src/include/pkinit_apple_utils.h +++ /dev/null @@ -1,155 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of Apple Inc. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Apple Inc. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - * pkinit_apple_utils.h - PKINIT utilities, Mac OS X version - * - * Created 19 May 2004 by Doug Mitchell. - */ - -#ifndef _PKINIT_APPLE_UTILS_H_ -#define _PKINIT_APPLE_UTILS_H_ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef PKI_DEBUG -#define PKI_DEBUG 0 -#endif - -#if PKI_DEBUG - -#include - -#define pkiDebug(args...) printf(args) -#define pkiCssmErr(str, rtn) cssmPerror(str, rtn) -#else -#define pkiDebug(args...) -#define pkiCssmErr(str, rtn) -#endif /* PKI_DEBUG */ - -/* - * Macros used to initialize a declared CSSM_DATA and krb5_data to zero/NULL values. - */ -#define INIT_CDATA(cd) cd = {0, NULL} -#define INIT_KDATA(kd) kd = {0, 0, NULL} - -/* attach/detach to/from CL */ -CSSM_RETURN pkiClDetachUnload(CSSM_CL_HANDLE clHand); -CSSM_CL_HANDLE pkiClStartup(void); - -/* - * CSSM_DATA <--> krb5_ui_4 - */ -krb5_error_code pkiDataToInt( - const CSSM_DATA *cdata, - krb5_int32 *i); /* RETURNED */ - -krb5_error_code pkiIntToData( - krb5_int32 num, - CSSM_DATA *cdata, /* allocated in coder space and RETURNED */ - SecAsn1CoderRef coder); - -/* - * raw data --> krb5_data - */ -krb5_error_code pkiDataToKrb5Data( - const void *data, - unsigned dataLen, - krb5_data *kd); /* content mallocd and RETURNED */ - -/* - * CSSM_DATA <--> krb5_data - * - * CSSM_DATA data is managed by a SecAsn1CoderRef; krb5_data.data is mallocd. - */ -krb5_error_code pkiCssmDataToKrb5Data( - const CSSM_DATA *cd, - krb5_data *kd); /* content mallocd and RETURNED */ - - -krb5_error_code pkiKrb5DataToCssm( - const krb5_data *kd, - CSSM_DATA *cdata, /* allocated in coder space and RETURNED */ - SecAsn1CoderRef coder); - -/* - * CFDataRef --> krb5_data, mallocing the destination contents. - */ -krb5_error_code pkiCfDataToKrb5Data( - CFDataRef cfData, - krb5_data *kd); /* content mallocd and RETURNED */ - -/* - * Non-mallocing conversion between CSSM_DATA and krb5_data - */ -#define PKI_CSSM_TO_KRB_DATA(cd, kd) \ - do { \ - (kd)->data = (char *)(cd)->Data; \ - (kd)->length = (cd)->Length; \ - } while (0) - -#define PKI_KRB_TO_CSSM_DATA(kd, cd) \ - do { \ - (cd)->Data = (uint8 *)(kd)->data; \ - (cd)->Length = (kd)->length; \ - } while (0) - -/* - * Compare to CSSM_DATAs. Return TRUE if they're the same else FALSE. - */ -krb5_boolean pkiCompareCssmData( - const CSSM_DATA *d1, - const CSSM_DATA *d2); - -/* - * krb5_timestamp <--> a mallocd string in generalized format - */ -krb5_error_code pkiKrbTimestampToStr( - krb5_timestamp kts, - char **str); /* mallocd and RETURNED */ - -krb5_error_code pkiTimeStrToKrbTimestamp( - const char *str, - unsigned len, - krb5_timestamp *kts); /* RETURNED */ - -/* - * How many items in a NULL-terminated array of pointers? - */ -unsigned pkiNssArraySize( - const void **array); - -#ifdef __cplusplus -} -#endif - -#endif /* _PKINIT_APPLE_UTILS_H_ */ diff --git a/src/include/pkinit_asn1.h b/src/include/pkinit_asn1.h deleted file mode 100644 index a1c4fe88e..000000000 --- a/src/include/pkinit_asn1.h +++ /dev/null @@ -1,172 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of Apple Inc. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Apple Inc. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - * pkinit_asn1.h - ASN.1 encode/decode routines for PKINIT - * - * Created 18 May 2004 by Doug Mitchell. - */ - -#ifndef _PKINIT_ASN1_H_ -#define _PKINIT_ASN1_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* RFC 3280 AlgorithmIdentifier */ -typedef struct { - krb5_data algorithm; /* OID */ - krb5_data parameters; /* ASN_ANY, defined by algorithm */ -} krb5int_algorithm_id; - -/* - * Encode and decode AuthPack, public key version (no Diffie-Hellman components). - */ -krb5_error_code krb5int_pkinit_auth_pack_encode( - krb5_timestamp kctime, - krb5_int32 cusec, /* microseconds */ - krb5_ui_4 nonce, - const krb5_checksum *pa_checksum, - const krb5int_algorithm_id *cms_types, /* optional */ - krb5_ui_4 num_cms_types, - krb5_data *auth_pack); /* mallocd and RETURNED */ - -/* all returned values are optional - pass NULL if you don't want them */ -krb5_error_code krb5int_pkinit_auth_pack_decode( - const krb5_data *auth_pack, /* DER encoded */ - krb5_timestamp *kctime, /* RETURNED */ - krb5_ui_4 *cusec, /* microseconds, RETURNED */ - krb5_ui_4 *nonce, /* RETURNED */ - krb5_checksum *pa_checksum, /* contents mallocd and RETURNED */ - krb5int_algorithm_id **cms_types, /* mallocd and RETURNED */ - krb5_ui_4 *num_cms_types); /* RETURNED */ - - -/* - * Given DER-encoded issuer and serial number, create an encoded - * IssuerAndSerialNumber. - */ -krb5_error_code krb5int_pkinit_issuer_serial_encode( - const krb5_data *issuer, /* DER encoded */ - const krb5_data *serial_num, - krb5_data *issuer_and_serial); /* content mallocd and RETURNED */ - -/* - * Decode IssuerAndSerialNumber. - */ -krb5_error_code krb5int_pkinit_issuer_serial_decode( - const krb5_data *issuer_and_serial, /* DER encoded */ - krb5_data *issuer, /* DER encoded, RETURNED */ - krb5_data *serial_num); /* RETURNED */ - -/* - * Top-level encode for PA-PK-AS-REQ. - * The signed_auth_pack field is wrapped in an OCTET STRING, content - * specific tag 0, during encode. - */ -krb5_error_code krb5int_pkinit_pa_pk_as_req_encode( - const krb5_data *signed_auth_pack, /* DER encoded ContentInfo */ - const krb5_data *trusted_CAs, /* optional: trustedCertifiers. Contents are - * DER-encoded issuer/serialNumbers. */ - krb5_ui_4 num_trusted_CAs, - const krb5_data *kdc_cert, /* optional kdcPkId, DER encoded issuer/serial */ - krb5_data *pa_pk_as_req); /* mallocd and RETURNED */ - -/* - * Top-level decode for PA-PK-AS-REQ. Does not perform cert verification on the - * ContentInfo; that is returned in BER-encoded form and processed elsewhere. - * The OCTET STRING wrapping the signed_auth_pack field is removed during the - * decode. - */ -krb5_error_code krb5int_pkinit_pa_pk_as_req_decode( - const krb5_data *pa_pk_as_req, - krb5_data *signed_auth_pack, /* DER encoded ContentInfo, RETURNED */ - /* - * Remainder are optionally RETURNED (specify NULL for pointers to - * items you're not interested in). - */ - krb5_ui_4 *num_trusted_CAs, /* sizeof trusted_CAs */ - krb5_data **trusted_CAs, /* mallocd array of DER-encoded TrustedCAs - * issuer/serial */ - krb5_data *kdc_cert); /* DER encoded issuer/serial */ - -/* - * Encode a ReplyKeyPack. The result is used as the Content of a SignedData. - */ -krb5_error_code krb5int_pkinit_reply_key_pack_encode( - const krb5_keyblock *key_block, - const krb5_checksum *checksum, - krb5_data *reply_key_pack); /* mallocd and RETURNED */ - -/* - * Decode a ReplyKeyPack. - */ -krb5_error_code krb5int_pkinit_reply_key_pack_decode( - const krb5_data *reply_key_pack, - krb5_keyblock *key_block, /* RETURNED */ - krb5_checksum *checksum); /* contents mallocd and RETURNED */ - -/* - * Encode a PA-PK-AS-REP. - * Exactly one of {dh_signed_data, enc_key_pack} is non-NULL on entry; - * each is a previously encoded item. - * - * dh_signed_data, if specified, is an encoded DHRepInfo. - * enc_key_pack, if specified, is EnvelopedData(signedData(ReplyKeyPack) - */ -krb5_error_code krb5int_pkinit_pa_pk_as_rep_encode( - const krb5_data *dh_signed_data, - const krb5_data *enc_key_pack, /* EnvelopedData(signedData(ReplyKeyPack) */ - krb5_data *pa_pk_as_rep); /* mallocd and RETURNED */ - -/* - * Decode a PA-PK-AS-REP. - * On successful return, exactly one of {dh_signed_data, enc_key_pack} - * will be non-NULL, each of which is mallocd and must be freed by - * caller. - * - * dh_signed_data, if returned, is an encoded DHRepInfo. - * enc_key_pack, if specified, is EnvelopedData(signedData(ReplyKeyPack) - */ -krb5_error_code krb5int_pkinit_pa_pk_as_rep_decode( - const krb5_data *pa_pk_as_rep, - krb5_data *dh_signed_data, - krb5_data *enc_key_pack); - -/* - * Given a DER encoded certificate, obtain the associated IssuerAndSerialNumber. - */ -krb5_error_code krb5int_pkinit_get_issuer_serial( - const krb5_data *cert, - krb5_data *issuer_and_serial); - -#ifdef __cplusplus -} -#endif - -#endif /* _PKINIT_ASN1_H_ */ diff --git a/src/include/pkinit_cert_store.h b/src/include/pkinit_cert_store.h deleted file mode 100644 index 3bec81e37..000000000 --- a/src/include/pkinit_cert_store.h +++ /dev/null @@ -1,163 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of Apple Inc. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Apple Inc. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - * pkinit_cert_store.h - PKINIT certificate storage/retrieval utilities - * - * Created 26 May 2004 by Doug Mitchell at Apple. - */ - -#ifndef _PKINIT_CERT_STORE_H_ -#define _PKINIT_CERT_STORE_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/* - * Opaque reference to a machine-dependent representation of a certificate - * which is capable of signing. On Mac OS X this is actually a SecIdentityRef. - */ -typedef void *krb5_pkinit_signing_cert_t; - -/* - * Opaque reference to a machine-dependent representation of a certificate. - * On Mac OS X this is actually a SecCertificateRef. - */ -typedef void *krb5_pkinit_cert_t; - -/* - * Opaque reference to a database in which PKINIT-related certificates are stored. - */ -typedef void *krb5_pkinit_cert_db_t; - -/* - * Obtain signing cert for specified principal. On successful return, - * caller must eventually release the cert with krb5_pkinit_release_cert(). - * - * Returns KRB5_PRINC_NOMATCH if client cert not found. - */ -krb5_error_code krb5_pkinit_get_client_cert( - const char *principal, /* full principal string */ - krb5_pkinit_signing_cert_t *client_cert); /* RETURNED */ - -/* - * Determine if the specified client has a signing cert. Returns TRUE - * if so, else returns FALSE. - */ -krb5_boolean krb5_pkinit_have_client_cert( - const char *principal); /* full principal string */ - -/* - * Store the specified certificate (or, more likely, some platform-dependent - * reference to it) as the specified principal's signing cert. Passing - * in NULL for the client_cert has the effect of deleting the relevant entry - * in the cert storage. - */ -krb5_error_code krb5_pkinit_set_client_cert_from_signing_cert( - const char *principal, /* full principal string */ - krb5_pkinit_signing_cert_t client_cert); -krb5_error_code krb5_pkinit_set_client_cert( - const char *principal, /* full principal string */ - krb5_pkinit_cert_t client_cert); - -/* - * Obtain a reference to the client's cert database. Specify either principal - * name or client_cert as obtained from krb5_pkinit_get_client_cert(). - */ -krb5_error_code krb5_pkinit_get_client_cert_db( - const char *principal, /* optional, full principal string */ - krb5_pkinit_signing_cert_t client_cert, /* optional, from krb5_pkinit_get_client_cert() */ - krb5_pkinit_cert_db_t *client_cert_db); /* RETURNED */ - -/* - * Obtain the KDC signing cert, with optional CA and specific cert specifiers. - * CAs and cert specifiers are in the form of DER-encoded issuerAndSerialNumbers. - * - * The client_spec argument is typically provided by the client as kdcPkId. - * - * If trusted_CAs and client_spec are NULL, a platform-dependent preferred - * KDC signing cert is returned, if one exists. - * - * On successful return, caller must eventually release the cert with - * krb5_pkinit_release_cert(). Outside of an unusual test configuration this = - * - * Returns KRB5_PRINC_NOMATCH if KDC cert not found. - * - */ -krb5_error_code krb5_pkinit_get_kdc_cert( - krb5_ui_4 num_trusted_CAs, /* sizeof *trusted_CAs */ - krb5_data *trusted_CAs, /* optional */ - krb5_data *client_spec, /* optional */ - krb5_pkinit_signing_cert_t *kdc_cert); /* RETURNED */ - -/* - * Obtain a reference to the KDC's cert database. - */ -krb5_error_code krb5_pkinit_get_kdc_cert_db( - krb5_pkinit_cert_db_t *kdc_cert_db); /* RETURNED */ - -/* - * Release certificate references obtained via krb5_pkinit_get_client_cert() and - * krb5_pkinit_get_kdc_cert(). - */ -extern void krb5_pkinit_release_cert( - krb5_pkinit_signing_cert_t cert); - -/* - * Release database references obtained via krb5_pkinit_get_client_cert_db() and - * krb5_pkinit_get_kdc_cert_db(). - */ -extern void krb5_pkinit_release_cert_db( - krb5_pkinit_cert_db_t cert_db); - -/* - * Obtain a mallocd C-string representation of a certificate's SHA1 digest. - * Only error is a NULL return indicating memory failure. - * Caller must free the returned string. - */ -char *krb5_pkinit_cert_hash_str( - const krb5_data *cert); - -/* - * Obtain a client's optional list of trusted KDC CA certs (trustedCertifiers) - * and/or trusted KDC cert (kdcPkId) for a given client and server. - * All returned values are mallocd and must be freed by caller; the contents - * of the krb5_datas are DER-encoded certificates. - */ -krb5_error_code krb5_pkinit_get_server_certs( - const char *client_principal, - const char *server_principal, - krb5_data **trusted_CAs, /* RETURNED, though return value may be NULL */ - krb5_ui_4 *num_trusted_CAs, /* RETURNED */ - krb5_data *kdc_cert); /* RETURNED, though may be 0/NULL */ - -#ifdef __cplusplus -} -#endif - -#endif /* _PKINIT_CERT_STORE_H_ */ diff --git a/src/include/pkinit_client.h b/src/include/pkinit_client.h deleted file mode 100644 index ed8e6e4da..000000000 --- a/src/include/pkinit_client.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of Apple Inc. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Apple Inc. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - * pkinit_client.h - Client side routines for PKINIT - * - * Created 20 May 2004 by Doug Mitchell at Apple. - */ - -#ifndef _PKINIT_CLIENT_H_ -#define _PKINIT_CLIENT_H_ - -#include -#include "pkinit_cms.h" -#include "pkinit_cert_store.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Create a PA-PK-AS-REQ message. - */ -krb5_error_code krb5int_pkinit_as_req_create( - krb5_context context, - krb5_timestamp kctime, - krb5_int32 cusec, /* microseconds */ - krb5_ui_4 nonce, - const krb5_checksum *cksum, - krb5_pkinit_signing_cert_t client_cert, /* required! */ - - /* - * trusted_CAs correponds to PA-PK-AS-REQ.trustedCertifiers. - * Expressed here as an optional list of DER-encoded certs. - */ - const krb5_data *trusted_CAs, - krb5_ui_4 num_trusted_CAs, - - /* optional PA-PK-AS-REQ.kdcPkId, expressed here as a - * DER-encoded cert */ - const krb5_data *kdc_cert, - krb5_data *as_req); /* mallocd and RETURNED */ - -/* - * Parse PA-PK-AS-REP message. Optionally evaluates the message's certificate chain. - * Optionally returns various components. - */ -krb5_error_code krb5int_pkinit_as_rep_parse( - krb5_context context, - const krb5_data *as_rep, - krb5_pkinit_signing_cert_t client_cert, /* required for decryption */ - krb5_keyblock *key_block, /* RETURNED */ - krb5_checksum *checksum, /* checksum of corresponding AS-REQ */ - /* contents mallocd and RETURNED */ - krb5int_cert_sig_status *cert_status, /* RETURNED */ - - /* - * Cert fields, all optionally RETURNED. - * - * signer_cert is the DER-encoded leaf cert from the incoming SignedData. - * all_certs is an array of all of the certs in the incoming SignedData, - * in full DER-encoded form. - */ - krb5_data *signer_cert, /* content mallocd */ - unsigned *num_all_certs, /* sizeof *all_certs */ - krb5_data **all_certs); /* krb5_data's and their content mallocd */ - -#ifdef __cplusplus -} -#endif - -#endif /* _PKINIT_CLIENT_H_ */ diff --git a/src/include/pkinit_cms.h b/src/include/pkinit_cms.h deleted file mode 100644 index 832e00d5b..000000000 --- a/src/include/pkinit_cms.h +++ /dev/null @@ -1,179 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of Apple Inc. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Apple Inc. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - * pkinit_apple_cms.h - CMS encode/decode routines, Mac OS X version - * - * Created 19 May 2004 by Doug Mitchell at Apple. - */ - -#ifndef _PKINIT_CMS_H_ -#define _PKINIT_CMS_H_ - -#include -#include "pkinit_cert_store.h" /* for krb5_pkinit_signing_cert_t */ -#include "pkinit_asn1.h" /* for krb5int_algorithm_id */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Define ContentType for a SignedData and EnvelopedData. - */ -enum { - /* normal CMS ContentTypes */ - ECT_Data, - ECT_SignedData, - ECT_EnvelopedData, - ECT_EncryptedData, - - /* - * For SignedAuthPack - * pkauthdata: { iso (1) org (3) dod (6) internet (1) - * security (5) kerberosv5 (2) pkinit (3) pkauthdata (1)} - */ - ECT_PkAuthData, - - /* - * For ReplyKeyPack - * pkrkeydata: { iso (1) org (3) dod (6) internet (1) - * security (5) kerberosv5 (2) pkinit (3) pkrkeydata (3) } - */ - ECT_PkReplyKeyKata, - - /* - * Other - i.e., unrecognized ContentType on decode. - */ - ECT_Other -}; -typedef krb5_int32 krb5int_cms_content_type; - -/* - * Result of certificate and signature verification. - */ -enum { - pki_cs_good = 0, - pki_not_signed, /* message not signed */ - pki_not_evaluated, /* signed, but not evaluated per caller request */ - /* remainder imply good signature on the message proper, i.e., these - * are all certificate errors. */ - pki_cs_sig_verify_fail, /* signature verification failed */ - pki_cs_bad_leaf, /* leaf/subject cert itself is plain bad */ - pki_cs_no_root, /* looks good but not verifiable to any root */ - pki_cs_unknown_root, /* verified to root we don't recognize */ - pki_cs_expired, /* expired */ - pki_cs_not_valid_yet, /* cert not valid yet */ - pki_cs_revoked, /* revoked via CRL or OCSP */ - pki_cs_untrusted, /* marked by user as untrusted */ - pki_bad_cms, /* CMS Format precluded verification */ - pki_bad_key_use, /* Bad ExtendedKeyUse or KeyUsage extension */ - pki_bad_digest, /* unacceptable CMS digest algorithm */ - pki_cs_other_err /* other cert verify error */ -}; -typedef krb5_int32 krb5int_cert_sig_status; - -/* - * Create a CMS message: either encrypted (EnvelopedData), signed - * (SignedData), or both (EnvelopedData(SignedData(content)). - * - * The message is signed iff signing_cert is non-NULL. - * The message is encrypted iff recip_cert is non-NULL. - * - * The content_type argument specifies to the eContentType - * for a SignedData's EncapsulatedContentInfo; it's ignored - * if the message is not to be signed. - * - * The cms_types argument optionally specifies a list, in order - * of decreasing preference, of CMS algorithms to use in the - * creation of the CMS message. - */ -krb5_error_code krb5int_pkinit_create_cms_msg( - const krb5_data *content, /* Content */ - krb5_pkinit_signing_cert_t signing_cert, /* optional: signed by this cert */ - const krb5_data *recip_cert, /* optional: encrypted with this cert */ - krb5int_cms_content_type content_type, /* OID for EncapsulatedData */ - krb5_ui_4 num_cms_types, /* optional */ - const krb5int_algorithm_id *cms_types, /* optional */ - krb5_data *content_info); /* contents mallocd and RETURNED */ - -/* - * Parse a ContentInfo as best we can. All returned fields are optional - - * pass NULL for values you don't need. - * - * If signer_cert_status is NULL on entry, NO signature or cert evaluation - * will be performed. - * - * The is_client_msg argument indicates whether the CMS message originated - * from the client (TRUE) or server (FALSE) and may be used in platform- - * dependent certificate evaluation. - * - * Note that signature and certificate verification errors do NOT cause - * this routine itself to return an error; caller is reponsible for - * handling such errors per the signer_cert_status out parameter. - */ -krb5_error_code krb5int_pkinit_parse_cms_msg( - const krb5_data *content_info, - krb5_pkinit_cert_db_t cert_db, /* may be required for SignedData */ - krb5_boolean is_client_msg, /* TRUE : msg is from client */ - krb5_boolean *is_signed, /* RETURNED */ - krb5_boolean *is_encrypted, /* RETURNED */ - krb5_data *raw_data, /* RETURNED */ - krb5int_cms_content_type *inner_content_type,/* Returned, ContentType of - * EncapsulatedData if - * *is_signed true */ - /* returned for type SignedData only */ - krb5_data *signer_cert, /* RETURNED */ - krb5int_cert_sig_status *signer_cert_status,/* RETURNED */ - unsigned *num_all_certs, /* size of *all_certs RETURNED */ - krb5_data **all_certs); /* entire cert chain RETURNED */ - -/* - * An AuthPack contains an optional set of AlgorithmIdentifiers - * which define the CMS algorithms supported by the client, in - * order of decreasing preference. - * - * krb5int_pkinit_get_cms_types() is a CMS-implementation-dependent - * function returning supported CMS algorithms in the form of a - * pointer and a length suitable for passing to - * krb5int_pkinit_auth_pack_encode. If no preference is to be expressed, - * this function returns NULL/0 (without returning a nonzero krb5_error_code). - * - * krb5int_pkinit_free_cms_types() frees the pointer obtained - * from krb5int_pkinit_get_cms_types() as necessary. - */ -krb5_error_code krb5int_pkinit_get_cms_types( - krb5int_algorithm_id **supported_cms_types, /* RETURNED */ - krb5_ui_4 *num_supported_cms_types); /* RETURNED */ - -krb5_error_code krb5int_pkinit_free_cms_types( - krb5int_algorithm_id *supported_cms_types, - krb5_ui_4 num_supported_cms_types); - -#ifdef __cplusplus -} -#endif - -#endif /* _PKINIT_CMS_H_ */ diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c index fd46e8396..55befefd1 100644 --- a/src/kadmin/cli/kadmin.c +++ b/src/kadmin/cli/kadmin.c @@ -943,9 +943,6 @@ static int kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc, long *mask, char **pass, krb5_boolean *randkey, krb5_key_salt_tuple **ks_tuple, int *n_ks_tuple, -#if APPLE_PKINIT - char **cert_hash, -#endif /* APPLE_PKINIT */ char *caller) { int i, attrib_set; @@ -958,9 +955,6 @@ kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc, *pass = NULL; *n_ks_tuple = 0; *ks_tuple = NULL; -#if APPLE_PKINIT - *cert_hash = NULL; -#endif /* APPLE_PKINIT */ time(&now); *randkey = FALSE; for (i = 1; i < argc - 1; i++) { @@ -1069,16 +1063,6 @@ kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc, *randkey = TRUE; continue; } -#if APPLE_PKINIT - if (strlen(argv[i]) == 9 && !strcmp("-certhash", argv[i])) { - if (++i > argc - 2) - return -1; - else { - *cert_hash = argv[i]; - continue; - } - } -#endif /* APPLE_PKINIT */ if (strlen(argv[i]) == 7 && !strcmp("-unlock", argv[i])) { unlock_princ(oprinc, mask, caller); continue; @@ -1211,32 +1195,17 @@ kadmin_addprinc(int argc, char *argv[]) krb5_error_code retval; char newpw[1024], dummybuf[256]; static char prompt1[1024], prompt2[1024]; -#if APPLE_PKINIT - char *cert_hash = NULL; -#endif /* APPLE_PKINIT */ /* Zero all fields in request structure */ memset(&princ, 0, sizeof(princ)); princ.attributes = 0; if (kadmin_parse_princ_args(argc, argv, &princ, &mask, &pass, &randkey, - &ks_tuple, &n_ks_tuple, -#if APPLE_PKINIT - &cert_hash, -#endif /* APPLE_PKINIT */ - "add_principal")) { + &ks_tuple, &n_ks_tuple, "add_principal")) { kadmin_addprinc_usage(); goto cleanup; } -#if APPLE_PKINIT - if(cert_hash != NULL) { - fprintf(stderr, - "add_principal: -certhash not allowed; use modify_principal\n"); - goto cleanup; - } -#endif /* APPLE_PKINIT */ - retval = krb5_unparse_name(context, princ.principal, &canon); if (retval) { com_err("add_principal", retval, _("while canonicalizing principal")); @@ -1334,9 +1303,6 @@ kadmin_modprinc(int argc, char *argv[]) krb5_boolean randkey = FALSE; int n_ks_tuple = 0; krb5_key_salt_tuple *ks_tuple = NULL; -#if APPLE_PKINIT - char *cert_hash = NULL; -#endif /* APPLE_PKINIT */ if (argc < 2) { kadmin_modprinc_usage(); @@ -1369,41 +1335,11 @@ kadmin_modprinc(int argc, char *argv[]) &princ, &mask, &pass, &randkey, &ks_tuple, &n_ks_tuple, -#if APPLE_PKINIT - &cert_hash, -#endif /* APPLE_PKINIT */ "modify_principal"); if (retval || ks_tuple != NULL || randkey || pass) { kadmin_modprinc_usage(); goto cleanup; } -#if APPLE_PKINIT - if (cert_hash) { - /* - * Use something other than the 1st preferred enctype here for fallback - * to pwd authentication - */ - krb5_key_salt_tuple key_salt = {ENCTYPE_ARCFOUR_HMAC, KRB5_KDB_SALTTYPE_CERTHASH}; - krb5_keyblock keyblock; - kadm5_ret_t kadmin_rtn; - - keyblock.magic = KV5M_KEYBLOCK; - keyblock.enctype = ENCTYPE_ARCFOUR_HMAC; - keyblock.length = strlen(cert_hash); - keyblock.contents = (krb5_octet *)cert_hash; - kadmin_rtn = kadm5_setkey_principal_3(handle, kprinc, - TRUE, /* keepold - we're appending */ - 1, &key_salt, - &keyblock, 1); - if (kadmin_rtn) { - com_err("modify_principal", kadmin_rtn, - "while adding certhash for \"%s\".", canon); - printf("realm %s data %s\n", (char *)kprinc->realm.data, (char *)kprinc->data->data); - goto cleanup; - } - retval = 0; - } -#endif /* APPLE_PKINIT */ if (mask) { /* Skip this if all we're doing is setting certhash. */ retval = kadm5_modify_principal(handle, &princ, mask); diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index 9234924b9..979239e5f 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -73,15 +73,6 @@ #include "adm_proto.h" #include "extern.h" -#if APPLE_PKINIT -#define AS_REQ_DEBUG 0 -#if AS_REQ_DEBUG -#define asReqDebug(args...) printf(args) -#else -#define asReqDebug(args...) -#endif -#endif /* APPLE_PKINIT */ - static krb5_error_code prepare_error_as(struct kdc_request_state *, krb5_kdc_req *, int, krb5_pa_data **, krb5_boolean, krb5_principal, @@ -254,13 +245,6 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode) goto egress; } -#if APPLE_PKINIT - asReqDebug("process_as_req reply realm %s name %s\n", - reply.client->realm.data, reply.client->data->data); -#endif /* APPLE_PKINIT */ - - - errcode = handle_authdata(kdc_context, state->c_flags, state->client, @@ -475,11 +459,6 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, state->req_pkt = req_pkt; state->from = from; -#if APPLE_PKINIT - asReqDebug("process_as_req top realm %s name %s\n", - request->client->realm.data, request->client->data->data); -#endif /* APPLE_PKINIT */ - if (state->request->msg_type != KRB5_AS_REQ) { state->status = "msg_type mismatch"; errcode = KRB5_BADMSGTYPE; diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index 31c2e144c..7cc0ccb28 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -81,10 +81,6 @@ #include "extern.h" #include #include "adm_proto.h" -#if APPLE_PKINIT -#include "pkinit_server.h" -#include "pkinit_cert_store.h" -#endif /* APPLE_PKINIT */ #include @@ -149,58 +145,8 @@ return_pw_salt(krb5_context, krb5_pa_data *padata, krb5_kdcpreauth_moddata moddata, krb5_kdcpreauth_modreq modreq); -#if APPLE_PKINIT -/* PKINIT preauth support */ -static krb5_error_code get_pkinit_edata( - krb5_context context, - krb5_kdc_req *request, - krb5_db_entry *client, - krb5_db_entry *server, - preauth_get_entry_data_proc get_entry_data, - void *pa_module_context, - krb5_pa_data *pa_data); -static krb5_error_code verify_pkinit_request( - krb5_context context, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_enc_tkt_part *enc_tkt_reply, - krb5_pa_data *data, - preauth_get_entry_data_proc get_entry_data, - void *pa_module_context, - void **pa_request_context, - krb5_data **e_data, - krb5_authdata ***authz_data); -static krb5_error_code return_pkinit_response( - krb5_context context, - krb5_pa_data * padata, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - preauth_get_entry_data_proc get_entry_data, - void *pa_module_context, - void **pa_request_context); -#endif /* APPLE_PKINIT */ static preauth_system static_preauth_systems[] = { -#if APPLE_PKINIT - { - "pkinit", - KRB5_PADATA_PK_AS_REQ, - PA_SUFFICIENT, - NULL, /* pa_sys_context */ - NULL, /* init */ - NULL, /* fini */ - get_pkinit_edata, - verify_pkinit_request, - return_pkinit_response, - NULL /* free_modreq */ - }, -#endif /* APPLE_PKINIT */ { "FAST", KRB5_PADATA_FX_FAST, @@ -1646,457 +1592,6 @@ cleanup: return retval; } - - -#if APPLE_PKINIT -/* PKINIT preauth support */ -#define PKINIT_DEBUG 0 -#if PKINIT_DEBUG -#define kdcPkinitDebug(args...) printf(args) -#else -#define kdcPkinitDebug(args...) -#endif - -/* - * get_edata() - our only job is to determine whether this KDC is capable of - * performing PKINIT. We infer that from the presence or absence of any - * KDC signing cert. - */ -static krb5_error_code get_pkinit_edata( - krb5_context context, - krb5_kdc_req *request, - krb5_db_entry *client, - krb5_db_entry *server, - preauth_get_entry_data_proc pkinit_get_entry_data, - void *pa_module_context, - krb5_pa_data *pa_data) -{ - krb5_pkinit_signing_cert_t cert = NULL; - krb5_error_code err = krb5_pkinit_get_kdc_cert(0, NULL, NULL, &cert); - - kdcPkinitDebug("get_pkinit_edata: kdc cert %s\n", err ? "NOT FOUND" : "FOUND"); - if(cert) { - krb5_pkinit_release_cert(cert); - } - return err; -} - -/* - * This is 0 only for testing until the KDC DB contains - * the hash of the client cert - */ -#define REQUIRE_CLIENT_CERT_MATCH 1 - -static krb5_error_code verify_pkinit_request( - krb5_context context, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_enc_tkt_part *enc_tkt_reply, - krb5_pa_data *data, - preauth_get_entry_data_proc pkinit_get_entry_data, - void *pa_module_context, - void **pa_request_context, - krb5_data **e_data, - krb5_authdata ***authz_data) -{ - krb5_error_code krtn; - krb5_data pa_data; - krb5_data *der_req = NULL; - krb5_boolean valid_cksum; - char *cert_hash = NULL; - unsigned cert_hash_len; - unsigned key_dex; - unsigned cert_match = 0; - krb5_keyblock decrypted_key, *mkey_ptr; - - /* the data we get from the AS-REQ */ - krb5_timestamp client_ctime = 0; - krb5_ui_4 client_cusec = 0; - krb5_timestamp kdc_ctime = 0; - krb5_int32 kdc_cusec = 0; - krb5_ui_4 nonce = 0; - krb5_checksum pa_cksum; - krb5int_cert_sig_status cert_sig_status; - krb5_data client_cert = {0, 0, NULL}; - - krb5_kdc_req *tmp_as_req = NULL; - - kdcPkinitDebug("verify_pkinit_request\n"); - - decrypted_key.contents = NULL; - pa_data.data = (char *)data->contents; - pa_data.length = data->length; - krtn = krb5int_pkinit_as_req_parse(context, &pa_data, - &client_ctime, &client_cusec, - &nonce, &pa_cksum, - &cert_sig_status, - NULL, NULL,/* num_cms_types, cms_types */ - &client_cert, /* signer_cert */ - /* remaining fields unused (for now) */ - NULL, NULL,/* num_all_certs, all_certs */ - NULL, NULL,/* num_trusted_CAs, trusted_CAs */ - NULL); /* kdc_cert */ - if(krtn) { - kdcPkinitDebug("pa_pk_as_req_parse returned %d; PKINIT aborting.\n", - (int)krtn); - return krtn; - } -#if PKINIT_DEBUG - if(cert_sig_status != pki_cs_good) { - kdcPkinitDebug("verify_pkinit_request: cert_sig_status %d\n", - (int)cert_sig_status); - } -#endif /* PKINIT_DEBUG */ - - /* - * Verify signature and cert. - * FIXME: The spec calls for an e-data with error-specific type to be - * returned on error here. TD_TRUSTED_CERTIFIERS - * to be returned to the client here. There is no way for a preauth - * module to pass back e-data to process_as_req at this time. We - * might want to add such capability via an out param to check_padata - * and to its callees. - */ - switch(cert_sig_status) { - case pki_cs_good: - break; - case pki_cs_sig_verify_fail: - /* no e-data */ - krtn = KDC_ERR_INVALID_SIG; - goto cleanup; - case pki_cs_no_root: - case pki_cs_unknown_root: - case pki_cs_untrusted: - /* - * Can't verify to known root. - * e-data TD_TRUSTED_CERTIFIERS - */ - kdcPkinitDebug("verify_pkinit_request: KDC_ERR_CANT_VERIFY_CERTIFICATE\n"); - krtn = KDC_ERR_CANT_VERIFY_CERTIFICATE; - goto cleanup; - case pki_cs_bad_leaf: - case pki_cs_expired: - case pki_cs_not_valid_yet: - /* - * Problems with client cert itself. - * e-data type TD_INVALID_CERTIFICATES - */ - krtn = KDC_ERR_INVALID_CERTIFICATE; - goto cleanup; - case pki_cs_revoked: - /* e-data type TD-INVALID-CERTIFICATES */ - krtn = KDC_ERR_REVOKED_CERTIFICATE; - goto cleanup; - case pki_bad_key_use: - krtn = KDC_ERR_INCONSISTENT_KEY_PURPOSE; - /* no e-data */ - goto cleanup; - case pki_bad_digest: - /* undefined (explicitly!) e-data */ - krtn = KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED; - goto cleanup; - case pki_bad_cms: - case pki_cs_other_err: - default: - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto cleanup; - } - - krtn = krb5_us_timeofday(context, &kdc_ctime, &kdc_cusec); - if(krtn) { - goto cleanup; - } - if (labs(kdc_ctime - client_ctime) > context->clockskew) { - kdcPkinitDebug("verify_pkinit_request: clock skew violation client %d svr %d\n", - (int)client_ctime, (int)kdc_ctime); - krtn = KRB5KRB_AP_ERR_SKEW; - goto cleanup; - } - - /* - * The KDC may have modified the request after decoding it. - * We need to compute the checksum on the data that - * came from the client. Therefore, we use the original - * packet contents. - */ - krtn = decode_krb5_as_req(req_pkt, &tmp_as_req); - if(krtn) { - kdcPkinitDebug("decode_krb5_as_req returned %d\n", (int)krtn); - goto cleanup; - } - - /* calculate and compare checksum */ - krtn = encode_krb5_kdc_req_body(tmp_as_req, &der_req); - if(krtn) { - kdcPkinitDebug("encode_krb5_kdc_req_body returned %d\n", (int)krtn); - goto cleanup; - } - krtn = krb5_c_verify_checksum(context, NULL, 0, der_req, - &pa_cksum, &valid_cksum); - if(krtn) { - kdcPkinitDebug("krb5_c_verify_checksum returned %d\n", (int)krtn); - goto cleanup; - } - if(!valid_cksum) { - kdcPkinitDebug("verify_pkinit_request: checksum error\n"); - krtn = KRB5KRB_AP_ERR_BAD_INTEGRITY; - goto cleanup; - } - -#if REQUIRE_CLIENT_CERT_MATCH - /* look up in the KDB to ensure correct client/cert binding */ - cert_hash = krb5_pkinit_cert_hash_str(&client_cert); - if(cert_hash == NULL) { - krtn = ENOMEM; - goto cleanup; - } - cert_hash_len = strlen(cert_hash); - for(key_dex=0; key_dexn_key_data; key_dex++) { - krb5_key_data *key_data = &client->key_data[key_dex]; - kdcPkinitDebug("--- key %u type[0] %u length[0] %u type[1] %u length[1] %u\n", - key_dex, - key_data->key_data_type[0], key_data->key_data_length[0], - key_data->key_data_type[1], key_data->key_data_length[1]); - if(key_data->key_data_type[1] != KRB5_KDB_SALTTYPE_CERTHASH) { - continue; - } - - /* - * Unfortunately this key is stored encrypted even though it's - * not sensitive... - */ - krtn = krb5_dbe_decrypt_key_data(context, NULL, key_data, - &decrypted_key, NULL); - if(krtn) { - kdcPkinitDebug("verify_pkinit_request: error decrypting cert hash block\n"); - break; - } - if((decrypted_key.contents != NULL) && - (cert_hash_len == decrypted_key.length) && - !memcmp(decrypted_key.contents, cert_hash, cert_hash_len)) { - cert_match = 1; - break; - } - } - if(decrypted_key.contents) { - krb5_free_keyblock_contents(context, &decrypted_key); - } - if(!cert_match) { - kdcPkinitDebug("verify_pkinit_request: client cert does not match\n"); - krtn = KDC_ERR_CLIENT_NOT_TRUSTED; - goto cleanup; - } -#endif /* REQUIRE_CLIENT_CERT_MATCH */ - krtn = 0; - setflag(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH); - -cleanup: - if(pa_cksum.contents) { - free(pa_cksum.contents); - } - if (tmp_as_req) { - krb5_free_kdc_req(context, tmp_as_req); - } - if (der_req) { - krb5_free_data(context, der_req); - } - if(cert_hash) { - free(cert_hash); - } - if(client_cert.data) { - free(client_cert.data); - } - kdcPkinitDebug("verify_pkinit_request: returning %d\n", (int)krtn); - return krtn; -} - -static krb5_error_code return_pkinit_response( - krb5_context context, - krb5_pa_data * padata, - krb5_db_entry *client, - krb5_data *req_pkt, - krb5_kdc_req *request, - krb5_kdc_rep *reply, - krb5_key_data *client_key, - krb5_keyblock *encrypting_key, - krb5_pa_data **send_pa, - preauth_get_entry_data_proc pkinit_get_entry_data, - void *pa_module_context, - void **pa_request_context) -{ - krb5_error_code krtn; - krb5_data pa_data; - krb5_pkinit_signing_cert_t signing_cert = NULL; - krb5_checksum as_req_checksum = {0}; - krb5_data *encoded_as_req = NULL; - krb5int_algorithm_id *cms_types = NULL; - krb5_ui_4 num_cms_types = 0; - - /* the data we get from the AS-REQ */ - krb5_ui_4 nonce = 0; - krb5_data client_cert = {0}; - - /* - * Trusted CA list and specific KC cert optionally obtained via - * krb5int_pkinit_as_req_parse(). All are DER-encoded - * issuerAndSerialNumbers. - */ - krb5_data *trusted_CAs = NULL; - krb5_ui_4 num_trusted_CAs; - krb5_data kdc_cert = {0}; - - if (padata == NULL) { - /* Client has to send us something */ - return 0; - } - - kdcPkinitDebug("return_pkinit_response\n"); - pa_data.data = (char *)padata->contents; - pa_data.length = padata->length; - - /* - * We've already verified; just obtain the fields we need to create a response - */ - krtn = krb5int_pkinit_as_req_parse(context, - &pa_data, - NULL, NULL, &nonce, /* ctime, cusec, nonce */ - NULL, NULL, /* pa_cksum, cert_status */ - &num_cms_types, &cms_types, - &client_cert, /* signer_cert: we encrypt for this */ - /* remaining fields unused (for now) */ - NULL, NULL, /* num_all_certs, all_certs */ - &num_trusted_CAs, &trusted_CAs, - &kdc_cert); - if(krtn) { - kdcPkinitDebug("pa_pk_as_req_parse returned %d; PKINIT aborting.\n", - (int)krtn); - goto cleanup; - } - if(client_cert.data == NULL) { - kdcPkinitDebug("pa_pk_as_req_parse failed to give a client_cert; aborting.\n"); - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto cleanup; - } - - if(krb5_pkinit_get_kdc_cert(num_trusted_CAs, trusted_CAs, - (kdc_cert.data ? &kdc_cert : NULL), - &signing_cert)) { - /* - * Since get_pkinit_edata was able to obtain *some* KDC cert, - * this means that we can't satisfy the client's requirement. - * FIXME - particular error status for this? - */ - kdcPkinitDebug("return_pkinit_response: NO appropriate signing cert!\n"); - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto cleanup; - } - - /* - * Cook up keyblock for caller and for outgoing AS-REP. - * FIXME how much is known to be valid about encrypting_key? - * Will encrypting_key->enctype always be valid here? Seems that - * if we allow for clients without a shared secret (i.e. preauth - * by PKINIT only) there won't be a valid encrypting_key set up - * here for us. - */ - krb5_free_keyblock_contents(context, encrypting_key); - krb5_c_make_random_key(context, encrypting_key->enctype, encrypting_key); - - /* calculate checksum of incoming AS-REQ */ - krtn = encode_krb5_as_req(request, &encoded_as_req); - if(krtn) { - kdcPkinitDebug("encode_krb5_as_req returned %d; PKINIT aborting.\n", (int)krtn); - goto cleanup; - } - krtn = krb5_c_make_checksum(context, context->kdc_req_sumtype, - encrypting_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, - encoded_as_req, &as_req_checksum); - if(krtn) { - goto cleanup; - } - - /* - * FIXME: here we assume that the client has one cert - the one that - * signed the AuthPack in the request (and that we therefore obtained from - * krb5int_pkinit_as_req_parse()), and the one we're using to encrypt the - * ReplyKeyPack with here. This may need rethinking. - */ - krtn = krb5int_pkinit_as_rep_create(context, - encrypting_key, &as_req_checksum, - signing_cert, TRUE, - &client_cert, - num_cms_types, cms_types, - num_trusted_CAs, trusted_CAs, - (kdc_cert.data ? &kdc_cert : NULL), - &pa_data); - if(krtn) { - kdcPkinitDebug("pa_pk_as_rep_create returned %d; PKINIT aborting.\n", - (int)krtn); - goto cleanup; - } - - *send_pa = (krb5_pa_data *)malloc(sizeof(krb5_pa_data)); - if(*send_pa == NULL) { - krtn = ENOMEM; - free(pa_data.data); - goto cleanup; - } - (*send_pa)->magic = KV5M_PA_DATA; - (*send_pa)->pa_type = KRB5_PADATA_PK_AS_REP; - (*send_pa)->length = pa_data.length; - (*send_pa)->contents = (krb5_octet *)pa_data.data; - krtn = 0; - -#if PKINIT_DEBUG - fprintf(stderr, "return_pkinit_response: SUCCESS\n"); - fprintf(stderr, "nonce 0x%x enctype %d keydata %02x %02x %02x %02x...\n", - (int)nonce, (int)encrypting_key->enctype, - encrypting_key->contents[0], encrypting_key->contents[1], - encrypting_key->contents[2], encrypting_key->contents[3]); -#endif - -cleanup: - /* all of this was allocd by krb5int_pkinit_as_req_parse() */ - if(signing_cert) { - krb5_pkinit_release_cert(signing_cert); - } - if(cms_types) { - unsigned dex; - krb5int_algorithm_id *alg_id; - - for(dex=0; dexalgorithm.data) { - free(alg_id->algorithm.data); - } - if(alg_id->parameters.data) { - free(alg_id->parameters.data); - } - } - free(cms_types); - } - if(trusted_CAs) { - unsigned dex; - for(dex=0; dex - -#define PKINIT_DEBUG 0 -#if PKINIT_DEBUG -#define pkiDebug(args...) printf(args) -#else -#define pkiDebug(args...) -#endif - -/* - * Parse PA-PK-AS-REQ message. Optionally evaluates the message's certificate chain. - * Optionally returns various components. - */ -krb5_error_code krb5int_pkinit_as_req_parse( - krb5_context context, - const krb5_data *as_req, - krb5_timestamp *kctime, /* optionally RETURNED */ - krb5_ui_4 *cusec, /* microseconds, optionally RETURNED */ - krb5_ui_4 *nonce, /* optionally RETURNED */ - krb5_checksum *pa_cksum, /* optional, contents mallocd and RETURNED */ - krb5int_cert_sig_status *cert_status,/* optionally RETURNED */ - krb5_ui_4 *num_cms_types, /* optionally RETURNED */ - krb5int_algorithm_id **cms_types, /* optionally mallocd and RETURNED */ - - /* - * Cert fields, all optionally RETURNED. - * - * signer_cert is the full X.509 leaf cert from the incoming SignedData. - * all_certs is an array of all of the certs in the incoming SignedData, - * in full X.509 form. - */ - krb5_data *signer_cert, /* content mallocd */ - krb5_ui_4 *num_all_certs, /* sizeof *all_certs */ - krb5_data **all_certs, /* krb5_data's and their content mallocd */ - - /* - * Array of trustedCertifiers, optionally RETURNED. These are DER-encoded - * issuer/serial numbers. - */ - krb5_ui_4 *num_trusted_CAs, /* sizeof *trusted_CAs */ - krb5_data **trusted_CAs, /* krb5_data's and their content mallocd */ - - /* KDC cert specified by client as kdcPkId. DER-encoded issuer/serial number. */ - krb5_data *kdc_cert) -{ - krb5_error_code krtn; - krb5_data signed_auth_pack = {0, 0, NULL}; - krb5_data raw_auth_pack = {0, 0, NULL}; - krb5_data *raw_auth_pack_p = NULL; - krb5_boolean proceed = FALSE; - krb5_boolean need_auth_pack = FALSE; - krb5int_cms_content_type content_type; - krb5_pkinit_cert_db_t cert_db = NULL; - krb5_boolean is_signed; - krb5_boolean is_encrypted; - - assert(as_req != NULL); - - /* - * We always have to decode the top-level AS-REQ... - */ - krtn = krb5int_pkinit_pa_pk_as_req_decode(as_req, &signed_auth_pack, - num_trusted_CAs, trusted_CAs, /* optional */ - kdc_cert); /* optional */ - if (krtn) { - pkiDebug("krb5int_pkinit_pa_pk_as_req_decode returned %d\n", (int)krtn); - return krtn; - } - - /* Do we need info about or from the ContentInto or AuthPack? */ - if ((kctime != NULL) || (cusec != NULL) || (nonce != NULL) || - (pa_cksum != NULL) || (cms_types != NULL)) { - need_auth_pack = TRUE; - raw_auth_pack_p = &raw_auth_pack; - } - if (need_auth_pack || (cert_status != NULL) || - (signer_cert != NULL) || (all_certs != NULL)) { - proceed = TRUE; - } - if (!proceed) { - krtn = 0; - goto err_out; - } - - /* Parse and possibly verify the ContentInfo */ - krtn = krb5_pkinit_get_kdc_cert_db(&cert_db); - if (krtn) { - pkiDebug("pa_pk_as_req_parse: error in krb5_pkinit_get_kdc_cert_db\n"); - goto err_out; - } - krtn = krb5int_pkinit_parse_cms_msg(&signed_auth_pack, cert_db, TRUE, - &is_signed, &is_encrypted, - raw_auth_pack_p, &content_type, signer_cert, cert_status, - num_all_certs, all_certs); - if (krtn) { - pkiDebug("krb5int_pkinit_parse_content_info returned %d\n", (int)krtn); - goto err_out; - } - - if (is_encrypted || !is_signed) { - pkiDebug("pkinit_parse_content_info: is_encrypted %s is_signed %s!\n", - is_encrypted ? "true" :"false", - is_signed ? "true" : "false"); - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto err_out; - } - if (content_type != ECT_PkAuthData) { - pkiDebug("authPack eContentType %d!\n", (int)content_type); - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto err_out; - } - - /* optionally parse contents of authPack */ - if (need_auth_pack) { - krtn = krb5int_pkinit_auth_pack_decode(&raw_auth_pack, kctime, - cusec, nonce, pa_cksum, - cms_types, num_cms_types); - if(krtn) { - pkiDebug("krb5int_pkinit_auth_pack_decode returned %d\n", (int)krtn); - goto err_out; - } - } - -err_out: - /* free temp mallocd data that we didn't pass back to caller */ - if(signed_auth_pack.data) { - free(signed_auth_pack.data); - } - if(raw_auth_pack.data) { - free(raw_auth_pack.data); - } - if(cert_db) { - krb5_pkinit_release_cert_db(cert_db); - } - return krtn; -} - -/* - * Create a PA-PK-AS-REP message, public key (no Diffie Hellman) version. - * - * PA-PK-AS-REP is based on ReplyKeyPack like so: - * - * PA-PK-AS-REP ::= EnvelopedData(SignedData(ReplyKeyPack)) - */ -krb5_error_code krb5int_pkinit_as_rep_create( - krb5_context context, - const krb5_keyblock *key_block, - const krb5_checksum *checksum, /* checksum of corresponding AS-REQ */ - krb5_pkinit_signing_cert_t signer_cert, /* server's cert */ - krb5_boolean include_server_cert,/* include signer_cert in SignerInfo */ - const krb5_data *recipient_cert, /* client's cert */ - - /* - * These correspond to the same out-parameters from - * krb5int_pkinit_as_req_parse(). All are optional. - */ - krb5_ui_4 num_cms_types, - const krb5int_algorithm_id *cms_types, - krb5_ui_4 num_trusted_CAs, - krb5_data *trusted_CAs, - krb5_data *kdc_cert, - - krb5_data *as_rep) /* mallocd and RETURNED */ -{ - krb5_data reply_key_pack = {0, 0, NULL}; - krb5_error_code krtn; - krb5_data enc_key_pack = {0, 0, NULL}; - - /* innermost content = ReplyKeyPack */ - krtn = krb5int_pkinit_reply_key_pack_encode(key_block, checksum, - &reply_key_pack); - if (krtn) { - return krtn; - } - - /* - * Put that in an EnvelopedData(SignedData) - * -- SignedData.EncapsulatedData.ContentType = id-pkinit-rkeyData - */ - krtn = krb5int_pkinit_create_cms_msg(&reply_key_pack, - signer_cert, - recipient_cert, - ECT_PkReplyKeyKata, - num_cms_types, cms_types, - &enc_key_pack); - if (krtn) { - goto err_out; - } - - /* - * Finally, wrap that inside of PA-PK-AS-REP - */ - krtn = krb5int_pkinit_pa_pk_as_rep_encode(NULL, &enc_key_pack, as_rep); - -err_out: - if (reply_key_pack.data) { - free(reply_key_pack.data); - } - if (enc_key_pack.data) { - free(enc_key_pack.data); - } - return krtn; -} - -#endif /* APPLE_PKINIT */ diff --git a/src/kdc/pkinit_server.h b/src/kdc/pkinit_server.h deleted file mode 100644 index 26e8edfc1..000000000 --- a/src/kdc/pkinit_server.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of Apple Inc. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Apple Inc. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - * pkinit_server.h - Server side routines for PKINIT - * - * Created 21 May 2004 by Doug Mitchell at Apple. - */ - -#ifndef _PKINIT_SERVER_H_ -#define _PKINIT_SERVER_H_ - -#include "krb5.h" -#include "pkinit_cms.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/* - * Parse PA-PK-AS-REQ message. Optionally evaluates the message's certificate chain - * if cert_status is non-NULL. Optionally returns various components. - */ -krb5_error_code krb5int_pkinit_as_req_parse( - krb5_context context, - const krb5_data *as_req, - krb5_timestamp *kctime, /* optionally RETURNED */ - krb5_ui_4 *cusec, /* microseconds, optionally RETURNED */ - krb5_ui_4 *nonce, /* optionally RETURNED */ - krb5_checksum *pa_cksum, /* optional, contents mallocd and RETURNED */ - krb5int_cert_sig_status *cert_status, /* optionally RETURNED */ - krb5_ui_4 *num_cms_types, /* optionally RETURNED */ - krb5int_algorithm_id **cms_types, /* optionally mallocd and RETURNED */ - - /* - * Cert fields, all optionally RETURNED. - * - * signer_cert is the full X.509 leaf cert from the incoming SignedData. - * all_certs is an array of all of the certs in the incoming SignedData, - * in full X.509 form. - */ - krb5_data *signer_cert, /* content mallocd */ - krb5_ui_4 *num_all_certs, /* sizeof *all_certs */ - krb5_data **all_certs, /* krb5_data's and their content mallocd */ - - /* - * Array of trustedCertifiers, optionally RETURNED. These are DER-encoded - * issuer/serial numbers. - */ - krb5_ui_4 *num_trusted_CAs, /* sizeof *trustedCAs */ - krb5_data **trusted_CAs, /* krb5_data's and their content mallocd */ - - /* KDC cert specified by client as kdcPkId. DER-encoded issuer/serial number. */ - krb5_data *kdc_cert); - - -/* - * Create a PA-PK-AS-REP message, public key (no Diffie Hellman) version. - * - * PA-PK-AS-REP is based on ReplyKeyPack like so: - * - * PA-PK-AS-REP ::= EnvelopedData(SignedData(ReplyKeyPack)) - */ -krb5_error_code krb5int_pkinit_as_rep_create( - krb5_context context, - const krb5_keyblock *key_block, - const krb5_checksum *checksum, /* checksum of corresponding AS-REQ */ - krb5_pkinit_signing_cert_t signer_cert, /* server's cert */ - krb5_boolean include_server_cert, /* include signer_cert in SignerInfo */ - const krb5_data *recipient_cert, /* client's cert */ - - /* - * These correspond to the same out-parameters from - * krb5int_pkinit_as_req_parse(). All are optional. - */ - krb5_ui_4 num_cms_types, - const krb5int_algorithm_id *cms_types, - krb5_ui_4 num_trusted_CAs, - krb5_data *trusted_CAs, - krb5_data *kdc_cert, - - /* result here, mallocd and RETURNED */ - krb5_data *as_rep); - -#ifdef __cplusplus -} -#endif - -#endif /* _PKINIT_SERVER_H_ */ diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c index 681b648b1..471834611 100644 --- a/src/lib/krb5/krb/get_in_tkt.c +++ b/src/lib/krb5/krb/get_in_tkt.c @@ -32,15 +32,6 @@ #include "fast.h" #include "init_creds_ctx.h" -#if APPLE_PKINIT -#define IN_TKT_DEBUG 0 -#if IN_TKT_DEBUG -#define inTktDebug(args...) printf(args) -#else -#define inTktDebug(args...) -#endif -#endif /* APPLE_PKINIT */ - /* some typedef's for the function args to make things look a bit cleaner */ static krb5_error_code make_preauth_list (krb5_context, @@ -202,17 +193,6 @@ verify_as_reply(krb5_context context, (request->till != 0) && (as_reply->enc_part2->times.renew_till > request->till)) ) { -#if APPLE_PKINIT - inTktDebug("verify_as_reply: KDCREP_MODIFIED\n"); -#if IN_TKT_DEBUG - if(request->client->realm.length && request->client->data->length) - inTktDebug("request: name %s realm %s\n", - request->client->realm.data, request->client->data->data); - if(as_reply->client->realm.length && as_reply->client->data->length) - inTktDebug("reply : name %s realm %s\n", - as_reply->client->realm.data, as_reply->client->data->data); -#endif -#endif /* APPLE_PKINIT */ return KRB5_KDCREP_MODIFIED; } diff --git a/src/lib/krb5/krb/pkinit_apple_asn1.c b/src/lib/krb5/krb/pkinit_apple_asn1.c deleted file mode 100644 index f968e05b7..000000000 --- a/src/lib/krb5/krb/pkinit_apple_asn1.c +++ /dev/null @@ -1,957 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of Apple Inc. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Apple Inc. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - * pkinit_apple_asn1.c - ASN.1 encode/decode routines for PKINIT, Mac OS X - * version - * - * Created 19 May 2004 by Doug Mitchell. - */ - -#if APPLE_PKINIT - -#include "k5-int.h" -#include "pkinit_asn1.h" -#include "pkinit_apple_utils.h" -#include -#include -#include -#include -#include -#include -#include -#include - -#pragma mark ----- utility routines ----- - -/* malloc a NULL-ed array of pointers of size num+1 */ -static void **pkiNssNullArray( - uint32 num, - SecAsn1CoderRef coder) -{ - unsigned len = (num + 1) * sizeof(void *); - void **p = (void **)SecAsn1Malloc(coder, len); - memset(p, 0, len); - return p; -} - -#pragma mark ====== begin PA-PK-AS-REQ components ====== - -#pragma mark ----- pkAuthenticator ----- - -/* - * There is a unique error code for "missing paChecksum", so we mark it here - * as optional so the decoder can process a pkAuthenticator without the - * checksum; caller must verify that paChecksum.Data != NULL. - */ -typedef struct { - CSSM_DATA cusec; /* INTEGER, microseconds */ - CSSM_DATA kctime; /* UTC time (with trailing 'Z') */ - CSSM_DATA nonce; /* INTEGER */ - CSSM_DATA paChecksum; /* OCTET STRING */ -} KRB5_PKAuthenticator; - -static const SecAsn1Template KRB5_PKAuthenticatorTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_PKAuthenticator) }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, - offsetof(KRB5_PKAuthenticator,cusec), - kSecAsn1IntegerTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1, - offsetof(KRB5_PKAuthenticator,kctime), - kSecAsn1GeneralizedTimeTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 2, - offsetof(KRB5_PKAuthenticator,nonce), - kSecAsn1IntegerTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | - SEC_ASN1_OPTIONAL | 3, - offsetof(KRB5_PKAuthenticator,paChecksum), - &kSecAsn1OctetStringTemplate }, - { 0 } -}; - -#pragma mark ----- AuthPack ----- - -typedef struct { - KRB5_PKAuthenticator pkAuth; - CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *pubKeyInfo; /* OPTIONAL */ - CSSM_X509_ALGORITHM_IDENTIFIER **supportedCMSTypes;/* OPTIONAL */ - CSSM_DATA *clientDHNonce; /* OPTIONAL */ -} KRB5_AuthPack; - -/* - * These are copied from keyTemplates.c in the libsecurity_asn1 project; - * they aren't public API. - */ - -/* AlgorithmIdentifier : CSSM_X509_ALGORITHM_IDENTIFIER */ -static const SecAsn1Template AlgorithmIDTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER) }, - { SEC_ASN1_OBJECT_ID, - offsetof(CSSM_X509_ALGORITHM_IDENTIFIER,algorithm), }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY, - offsetof(CSSM_X509_ALGORITHM_IDENTIFIER,parameters), }, - { 0, } -}; - - -/* SubjectPublicKeyInfo : CSSM_X509_SUBJECT_PUBLIC_KEY_INFO */ -static const SecAsn1Template SubjectPublicKeyInfoTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO) }, - { SEC_ASN1_INLINE, - offsetof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO,algorithm), - AlgorithmIDTemplate }, - { SEC_ASN1_BIT_STRING, - offsetof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO,subjectPublicKey), }, - { 0, } -}; - -/* end of copied templates */ - -static const SecAsn1Template kSecAsn1SequenceOfAlgIdTemplate[] = { - { SEC_ASN1_SEQUENCE_OF, 0, AlgorithmIDTemplate } -}; - -static const SecAsn1Template KRB5_AuthPackTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_AuthPack) }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, - offsetof(KRB5_AuthPack,pkAuth), - KRB5_PKAuthenticatorTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | - SEC_ASN1_EXPLICIT | SEC_ASN1_POINTER | 1, - offsetof(KRB5_AuthPack,pubKeyInfo), - SubjectPublicKeyInfoTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | - SEC_ASN1_EXPLICIT | SEC_ASN1_POINTER | 2, - offsetof(KRB5_AuthPack,supportedCMSTypes), - kSecAsn1SequenceOfAlgIdTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | - SEC_ASN1_EXPLICIT | SEC_ASN1_POINTER | 3, - offsetof(KRB5_AuthPack,clientDHNonce), - kSecAsn1OctetStringTemplate }, - { 0 } -}; - -/* - * Encode AuthPack, public key version (no Diffie-Hellman components). - */ -krb5_error_code krb5int_pkinit_auth_pack_encode( - krb5_timestamp kctime, - krb5_int32 cusec, /* microseconds */ - krb5_ui_4 nonce, - const krb5_checksum *pa_checksum, - const krb5int_algorithm_id *cms_types, /* optional */ - krb5_ui_4 num_cms_types, - krb5_data *auth_pack) /* mallocd and RETURNED */ -{ - KRB5_AuthPack localAuthPack; - SecAsn1CoderRef coder; - CSSM_DATA *cksum = &localAuthPack.pkAuth.paChecksum; - krb5_error_code ourRtn = 0; - CSSM_DATA ber = {0, NULL}; - OSStatus ortn; - char *timeStr = NULL; - - if(SecAsn1CoderCreate(&coder)) { - return ENOMEM; - } - memset(&localAuthPack, 0, sizeof(localAuthPack)); - if(pkiKrbTimestampToStr(kctime, &timeStr)) { - ourRtn = -1; - goto errOut; - } - localAuthPack.pkAuth.kctime.Data = (uint8 *)timeStr; - localAuthPack.pkAuth.kctime.Length = strlen(timeStr); - if(pkiIntToData(cusec, &localAuthPack.pkAuth.cusec, coder)) { - ourRtn = ENOMEM; - goto errOut; - } - if(pkiIntToData(nonce, &localAuthPack.pkAuth.nonce, coder)) { - ourRtn = ENOMEM; - goto errOut; - } - cksum->Data = (uint8 *)pa_checksum->contents; - cksum->Length = pa_checksum->length; - - if((cms_types != NULL) && (num_cms_types != 0)) { - unsigned dex; - CSSM_X509_ALGORITHM_IDENTIFIER **algIds; - - /* build a NULL_terminated array of CSSM_X509_ALGORITHM_IDENTIFIERs */ - localAuthPack.supportedCMSTypes = (CSSM_X509_ALGORITHM_IDENTIFIER **) - SecAsn1Malloc(coder, - (num_cms_types + 1) * sizeof(CSSM_X509_ALGORITHM_IDENTIFIER *)); - algIds = localAuthPack.supportedCMSTypes; - for(dex=0; dexalgorithm, coder); - if(cms_types[dex].parameters.data != NULL) { - pkiKrb5DataToCssm(&cms_types[dex].parameters, - &algIds[dex]->parameters, coder); - } - else { - algIds[dex]->parameters.Data = NULL; - algIds[dex]->parameters.Length = 0; - } - } - algIds[num_cms_types] = NULL; - } - ortn = SecAsn1EncodeItem(coder, &localAuthPack, KRB5_AuthPackTemplate, &ber); - if(ortn) { - ourRtn = ENOMEM; - goto errOut; - } - - if(pkiCssmDataToKrb5Data(&ber, auth_pack)) { - ourRtn = ENOMEM; - } - else { - auth_pack->magic = KV5M_AUTHENTICATOR; - ourRtn = 0; - } -errOut: - SecAsn1CoderRelease(coder); - return ourRtn; -} - -/* - * Decode AuthPack, public key version (no Diffie-Hellman components). - */ -krb5_error_code krb5int_pkinit_auth_pack_decode( - const krb5_data *auth_pack, /* DER encoded */ - krb5_timestamp *kctime, /* RETURNED */ - krb5_ui_4 *cusec, /* microseconds, RETURNED */ - krb5_ui_4 *nonce, /* RETURNED */ - krb5_checksum *pa_checksum, /* contents mallocd and RETURNED */ - krb5int_algorithm_id **cms_types, /* optionally mallocd and RETURNED */ - krb5_ui_4 *num_cms_types) /* optionally RETURNED */ -{ - KRB5_AuthPack localAuthPack; - SecAsn1CoderRef coder; - CSSM_DATA der = {0, NULL}; - krb5_error_code ourRtn = 0; - CSSM_DATA *cksum = &localAuthPack.pkAuth.paChecksum; - - /* Decode --> localAuthPack */ - if(SecAsn1CoderCreate(&coder)) { - return ENOMEM; - } - PKI_KRB_TO_CSSM_DATA(auth_pack, &der); - memset(&localAuthPack, 0, sizeof(localAuthPack)); - if(SecAsn1DecodeData(coder, &der, KRB5_AuthPackTemplate, &localAuthPack)) { - ourRtn = ASN1_BAD_FORMAT; - goto errOut; - } - - /* optionally Convert KRB5_AuthPack to caller's params */ - if(kctime) { - if((ourRtn = pkiTimeStrToKrbTimestamp((char *)localAuthPack.pkAuth.kctime.Data, - localAuthPack.pkAuth.kctime.Length, kctime))) { - goto errOut; - } - } - if(cusec) { - if((ourRtn = pkiDataToInt(&localAuthPack.pkAuth.cusec, (krb5_int32 *)cusec))) { - goto errOut; - } - } - if(nonce) { - if((ourRtn = pkiDataToInt(&localAuthPack.pkAuth.nonce, (krb5_int32 *)nonce))) { - goto errOut; - } - } - if(pa_checksum) { - if(cksum->Length == 0) { - /* This is the unique error for "no paChecksum" */ - ourRtn = KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED; - goto errOut; - } - else { - pa_checksum->contents = (krb5_octet *)malloc(cksum->Length); - if(pa_checksum->contents == NULL) { - ourRtn = ENOMEM; - goto errOut; - } - pa_checksum->length = cksum->Length; - memmove(pa_checksum->contents, cksum->Data, pa_checksum->length); - pa_checksum->magic = KV5M_CHECKSUM; - /* This used to be encoded with the checksum but no more... */ - pa_checksum->checksum_type = CKSUMTYPE_NIST_SHA; - } - } - if(cms_types) { - if(localAuthPack.supportedCMSTypes == NULL) { - *cms_types = NULL; - *num_cms_types = 0; - } - else { - /* - * Convert NULL-terminated array of CSSM-style algIds to - * krb5int_algorithm_ids. - */ - unsigned dex; - unsigned num_types = 0; - CSSM_X509_ALGORITHM_IDENTIFIER **alg_ids; - krb5int_algorithm_id *kalg_ids; - - for(alg_ids=localAuthPack.supportedCMSTypes; - *alg_ids; - alg_ids++) { - num_types++; - } - *cms_types = kalg_ids = (krb5int_algorithm_id *)calloc(num_types, - sizeof(krb5int_algorithm_id)); - *num_cms_types = num_types; - alg_ids = localAuthPack.supportedCMSTypes; - for(dex=0; dexalgorithm.Data) { - pkiCssmDataToKrb5Data(&alg_ids[dex]->algorithm, - &kalg_ids[dex].algorithm); - } - if(alg_ids[dex]->parameters.Data) { - pkiCssmDataToKrb5Data(&alg_ids[dex]->parameters, - &kalg_ids[dex].parameters); - } - } - } - } - ourRtn = 0; -errOut: - SecAsn1CoderRelease(coder); - return ourRtn; -} - -#pragma mark ----- IssuerAndSerialNumber ----- - -/* - * Issuer/serial number - specify issuer as ASN_ANY because we can get it from - * CL in DER-encoded state. - */ -typedef struct { - CSSM_DATA derIssuer; - CSSM_DATA serialNumber; -} KRB5_IssuerAndSerial; - -static const SecAsn1Template KRB5_IssuerAndSerialTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_IssuerAndSerial) }, - { SEC_ASN1_ANY, offsetof(KRB5_IssuerAndSerial, derIssuer) }, - { SEC_ASN1_INTEGER, offsetof(KRB5_IssuerAndSerial, serialNumber) }, - { 0 } -}; - -/* - * Given DER-encoded issuer and serial number, create an encoded - * IssuerAndSerialNumber. - */ -krb5_error_code krb5int_pkinit_issuer_serial_encode( - const krb5_data *issuer, /* DER encoded */ - const krb5_data *serial_num, - krb5_data *issuer_and_serial) /* content mallocd and RETURNED */ -{ - KRB5_IssuerAndSerial issuerSerial; - SecAsn1CoderRef coder; - CSSM_DATA ber = {0, NULL}; - OSStatus ortn; - - if(SecAsn1CoderCreate(&coder)) { - return ENOMEM; - } - PKI_KRB_TO_CSSM_DATA(issuer, &issuerSerial.derIssuer); - PKI_KRB_TO_CSSM_DATA(serial_num, &issuerSerial.serialNumber); - ortn = SecAsn1EncodeItem(coder, &issuerSerial, KRB5_IssuerAndSerialTemplate, &ber); - if(ortn) { - ortn = ENOMEM; - goto errOut; - } - ortn = pkiCssmDataToKrb5Data(&ber, issuer_and_serial); -errOut: - SecAsn1CoderRelease(coder); - return ortn; -} - -/* - * Decode IssuerAndSerialNumber. - */ -krb5_error_code krb5int_pkinit_issuer_serial_decode( - const krb5_data *issuer_and_serial, /* DER encoded */ - krb5_data *issuer, /* DER encoded, RETURNED */ - krb5_data *serial_num) /* RETURNED */ -{ - KRB5_IssuerAndSerial issuerSerial; - SecAsn1CoderRef coder; - CSSM_DATA der = {issuer_and_serial->length, (uint8 *)issuer_and_serial->data}; - krb5_error_code ourRtn = 0; - - /* Decode --> issuerSerial */ - if(SecAsn1CoderCreate(&coder)) { - return ENOMEM; - } - memset(&issuerSerial, 0, sizeof(issuerSerial)); - if(SecAsn1DecodeData(coder, &der, KRB5_IssuerAndSerialTemplate, &issuerSerial)) { - ourRtn = ASN1_BAD_FORMAT; - goto errOut; - } - - /* Convert KRB5_IssuerAndSerial to caller's params */ - if((ourRtn = pkiCssmDataToKrb5Data(&issuerSerial.derIssuer, issuer))) { - goto errOut; - } - if((ourRtn = pkiCssmDataToKrb5Data(&issuerSerial.serialNumber, serial_num))) { - ourRtn = ENOMEM; - goto errOut; - } - -errOut: - SecAsn1CoderRelease(coder); - return ourRtn; -} - -#pragma mark ----- ExternalPrincipalIdentifier ----- - -/* - * Shown here for completeness; this module only implements the - * issuerAndSerialNumber option. - */ -typedef struct { - CSSM_DATA subjectName; /* [0] IMPLICIT OCTET STRING OPTIONAL */ - /* contents = encoded Name */ - CSSM_DATA issuerAndSerialNumber; /* [1] IMPLICIT OCTET STRING OPTIONAL */ - /* contents = encoded Issuer&Serial */ - CSSM_DATA subjectKeyIdentifier; /* [2] IMPLICIT OCTET STRING OPTIONAL */ - /* contents = encoded subjectKeyIdentifier extension */ -} KRB5_ExternalPrincipalIdentifier; - -static const SecAsn1Template KRB5_ExternalPrincipalIdentifierTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_ExternalPrincipalIdentifier) }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_OPTIONAL | 0, - offsetof(KRB5_ExternalPrincipalIdentifier, subjectName), - kSecAsn1OctetStringTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_OPTIONAL | 1, - offsetof(KRB5_ExternalPrincipalIdentifier, issuerAndSerialNumber), - kSecAsn1OctetStringTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_OPTIONAL | 2, - offsetof(KRB5_ExternalPrincipalIdentifier, subjectKeyIdentifier), - kSecAsn1OctetStringTemplate }, - { 0 } -}; - -static const SecAsn1Template KRB5_SequenceOfExternalPrincipalIdentifierTemplate[] = { - { SEC_ASN1_SEQUENCE_OF, 0, KRB5_ExternalPrincipalIdentifierTemplate } -}; - -#pragma mark ----- PA-PK-AS-REQ ----- - -/* - * Top-level PA-PK-AS-REQ. All fields except for trusted_CAs are pre-encoded - * before we encode this and are still DER-encoded after we decode. - * The signedAuthPack and kdcPkId fields are wrapped in OCTET STRINGs - * during encode; we strip off the OCTET STRING wrappers during decode. - */ -typedef struct { - CSSM_DATA signedAuthPack; /* ContentInfo, SignedData */ - /* Content is KRB5_AuthPack */ - KRB5_ExternalPrincipalIdentifier - **trusted_CAs; /* optional */ - CSSM_DATA kdcPkId; /* optional */ -} KRB5_PA_PK_AS_REQ; - -static const SecAsn1Template KRB5_PA_PK_AS_REQTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_PA_PK_AS_REQ) }, - { SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(KRB5_PA_PK_AS_REQ, signedAuthPack), - kSecAsn1OctetStringTemplate }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | - SEC_ASN1_EXPLICIT | 1, - offsetof(KRB5_PA_PK_AS_REQ, trusted_CAs), - KRB5_SequenceOfExternalPrincipalIdentifierTemplate }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | 2, - offsetof(KRB5_PA_PK_AS_REQ, kdcPkId), - kSecAsn1AnyTemplate }, - { 0 } -}; - -/* - * Top-level encode for PA-PK-AS-REQ. - */ -krb5_error_code krb5int_pkinit_pa_pk_as_req_encode( - const krb5_data *signed_auth_pack, /* DER encoded ContentInfo */ - const krb5_data *trusted_CAs, /* optional: trustedCertifiers. Contents are - * DER-encoded issuer/serialNumbers. */ - krb5_ui_4 num_trusted_CAs, - const krb5_data *kdc_cert, /* optional kdcPkId, DER encoded issuer/serial */ - krb5_data *pa_pk_as_req) /* mallocd and RETURNED */ -{ - KRB5_PA_PK_AS_REQ req; - SecAsn1CoderRef coder; - CSSM_DATA ber = {0, NULL}; - OSStatus ortn; - unsigned dex; - - assert(signed_auth_pack != NULL); - assert(pa_pk_as_req != NULL); - - if(SecAsn1CoderCreate(&coder)) { - return ENOMEM; - } - - /* krb5_data ==> CSSM format */ - - memset(&req, 0, sizeof(req)); - PKI_KRB_TO_CSSM_DATA(signed_auth_pack, &req.signedAuthPack); - if(num_trusted_CAs) { - /* - * Set up a NULL-terminated array of KRB5_ExternalPrincipalIdentifier - * pointers. We malloc the actual KRB5_ExternalPrincipalIdentifiers as - * a contiguous array; it's in temp SecAsn1CoderRef memory. The referents - * are just dropped in from the caller's krb5_datas. - */ - KRB5_ExternalPrincipalIdentifier *cas = - (KRB5_ExternalPrincipalIdentifier *)SecAsn1Malloc(coder, - num_trusted_CAs * sizeof(KRB5_ExternalPrincipalIdentifier)); - req.trusted_CAs = - (KRB5_ExternalPrincipalIdentifier **) - pkiNssNullArray(num_trusted_CAs, coder); - for(dex=0; dex KRB5_PA_PK_AS_REQ */ - if(SecAsn1CoderCreate(&coder)) { - return ENOMEM; - } - PKI_KRB_TO_CSSM_DATA(pa_pk_as_req, &der); - memset(&asReq, 0, sizeof(asReq)); - if(SecAsn1DecodeData(coder, &der, KRB5_PA_PK_AS_REQTemplate, &asReq)) { - ourRtn = ASN1_BAD_FORMAT; - goto errOut; - } - - /* Convert decoded results to caller's args; each is optional */ - if(signed_auth_pack != NULL) { - if((ourRtn = pkiCssmDataToKrb5Data(&asReq.signedAuthPack, signed_auth_pack))) { - goto errOut; - } - } - if(asReq.trusted_CAs && (trusted_CAs != NULL)) { - /* NULL-terminated array of CSSM_DATA ptrs */ - unsigned numCas = pkiNssArraySize((const void **)asReq.trusted_CAs); - unsigned dex; - krb5_data *kdcCas; - - kdcCas = (krb5_data *)malloc(sizeof(krb5_data) * numCas); - if(kdcCas == NULL) { - ourRtn = ENOMEM; - goto errOut; - } - for(dex=0; dexissuerAndSerialNumber.Data) { - /* the only variant we support */ - pkiCssmDataToKrb5Data(&epi->issuerAndSerialNumber, &kdcCas[dex]); - } - } - *trusted_CAs = kdcCas; - *num_trusted_CAs = numCas; - } - if(asReq.kdcPkId.Data && kdc_cert) { - if((ourRtn = pkiCssmDataToKrb5Data(&asReq.kdcPkId, kdc_cert))) { - goto errOut; - } - } -errOut: - SecAsn1CoderRelease(coder); - return ourRtn; -} - -#pragma mark ====== begin PA-PK-AS-REP components ====== - -typedef struct { - CSSM_DATA subjectPublicKey; /* BIT STRING */ - CSSM_DATA nonce; /* from KRB5_PKAuthenticator.nonce */ - CSSM_DATA *expiration; /* optional UTC time */ -} KRB5_KDC_DHKeyInfo; - -typedef struct { - CSSM_DATA keyType; - CSSM_DATA keyValue; -} KRB5_EncryptionKey; - -static const SecAsn1Template KRB5_EncryptionKeyTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_EncryptionKey) }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, - offsetof(KRB5_EncryptionKey, keyType), - kSecAsn1IntegerTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1, - offsetof(KRB5_EncryptionKey, keyValue), - kSecAsn1OctetStringTemplate }, - { 0 } -}; - -#pragma mark ----- Checksum ----- - -typedef struct { - CSSM_DATA checksumType; - CSSM_DATA checksum; -} KRB5_Checksum; - -static const SecAsn1Template KRB5_ChecksumTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_Checksum) }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, - offsetof(KRB5_Checksum,checksumType), - kSecAsn1IntegerTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1, - offsetof(KRB5_Checksum,checksum), - kSecAsn1OctetStringTemplate }, - { 0 } -}; - -typedef struct { - KRB5_EncryptionKey encryptionKey; - KRB5_Checksum asChecksum; -} KRB5_ReplyKeyPack; - -static const SecAsn1Template KRB5_ReplyKeyPackTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_ReplyKeyPack) }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 0, - offsetof(KRB5_ReplyKeyPack, encryptionKey), - KRB5_EncryptionKeyTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_EXPLICIT | 1, - offsetof(KRB5_ReplyKeyPack,asChecksum), - KRB5_ChecksumTemplate }, - { 0 } -}; - -/* - * Encode a ReplyKeyPack. The result is used as the Content of a SignedData. - */ -krb5_error_code krb5int_pkinit_reply_key_pack_encode( - const krb5_keyblock *key_block, - const krb5_checksum *checksum, - krb5_data *reply_key_pack) /* mallocd and RETURNED */ -{ - KRB5_ReplyKeyPack repKeyPack; - SecAsn1CoderRef coder; - krb5_error_code ourRtn = 0; - CSSM_DATA der = {0, NULL}; - OSStatus ortn; - KRB5_EncryptionKey *encryptKey = &repKeyPack.encryptionKey; - KRB5_Checksum *cksum = &repKeyPack.asChecksum; - - if(SecAsn1CoderCreate(&coder)) { - return ENOMEM; - } - memset(&repKeyPack, 0, sizeof(repKeyPack)); - - if((ourRtn = pkiIntToData(key_block->enctype, &encryptKey->keyType, coder))) { - goto errOut; - } - encryptKey->keyValue.Length = key_block->length, - encryptKey->keyValue.Data = (uint8 *)key_block->contents; - - if((ourRtn = pkiIntToData(checksum->checksum_type, &cksum->checksumType, coder))) { - goto errOut; - } - cksum->checksum.Data = (uint8 *)checksum->contents; - cksum->checksum.Length = checksum->length; - - ortn = SecAsn1EncodeItem(coder, &repKeyPack, KRB5_ReplyKeyPackTemplate, &der); - if(ortn) { - ourRtn = ENOMEM; - goto errOut; - } - ourRtn = pkiCssmDataToKrb5Data(&der, reply_key_pack); -errOut: - SecAsn1CoderRelease(coder); - return ourRtn; -} - -/* - * Decode a ReplyKeyPack. - */ -krb5_error_code krb5int_pkinit_reply_key_pack_decode( - const krb5_data *reply_key_pack, - krb5_keyblock *key_block, /* RETURNED */ - krb5_checksum *checksum) /* contents mallocd and RETURNED */ -{ - KRB5_ReplyKeyPack repKeyPack; - SecAsn1CoderRef coder; - krb5_error_code ourRtn = 0; - KRB5_EncryptionKey *encryptKey = &repKeyPack.encryptionKey; - CSSM_DATA der = {reply_key_pack->length, (uint8 *)reply_key_pack->data}; - krb5_data tmpData; - KRB5_Checksum *cksum = &repKeyPack.asChecksum; - - /* Decode --> KRB5_ReplyKeyPack */ - if(SecAsn1CoderCreate(&coder)) { - return ENOMEM; - } - memset(&repKeyPack, 0, sizeof(repKeyPack)); - if(SecAsn1DecodeData(coder, &der, KRB5_ReplyKeyPackTemplate, &repKeyPack)) { - ourRtn = ASN1_BAD_FORMAT; - goto errOut; - } - - if((ourRtn = pkiDataToInt(&encryptKey->keyType, (krb5_int32 *)&key_block->enctype))) { - goto errOut; - } - if((ourRtn = pkiCssmDataToKrb5Data(&encryptKey->keyValue, &tmpData))) { - goto errOut; - } - key_block->contents = (krb5_octet *)tmpData.data; - key_block->length = tmpData.length; - - if((ourRtn = pkiDataToInt(&cksum->checksumType, &checksum->checksum_type))) { - goto errOut; - } - checksum->contents = (krb5_octet *)malloc(cksum->checksum.Length); - if(checksum->contents == NULL) { - ourRtn = ENOMEM; - goto errOut; - } - checksum->length = cksum->checksum.Length; - memmove(checksum->contents, cksum->checksum.Data, checksum->length); - checksum->magic = KV5M_CHECKSUM; - -errOut: - SecAsn1CoderRelease(coder); - return ourRtn; -} - - -#pragma mark ----- KRB5_PA_PK_AS_REP ----- -/* - * Top-level PA-PK-AS-REP. Exactly one of the optional fields must be present. - */ -typedef struct { - CSSM_DATA *dhSignedData; /* ContentInfo, SignedData */ - /* Content is KRB5_KDC_DHKeyInfo */ - CSSM_DATA *encKeyPack; /* ContentInfo, SignedData */ - /* Content is ReplyKeyPack */ -} KRB5_PA_PK_AS_REP; - -static const SecAsn1Template KRB5_PA_PK_AS_REPTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(KRB5_PA_PK_AS_REP) }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | - SEC_ASN1_EXPLICIT | 0, - offsetof(KRB5_PA_PK_AS_REP, dhSignedData), - kSecAsn1PointerToAnyTemplate }, - { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | - SEC_ASN1_EXPLICIT | 1, - offsetof(KRB5_PA_PK_AS_REP, encKeyPack), - kSecAsn1PointerToAnyTemplate }, - { 0 } -}; - -/* - * Encode a KRB5_PA_PK_AS_REP. - */ -krb5_error_code krb5int_pkinit_pa_pk_as_rep_encode( - const krb5_data *dh_signed_data, - const krb5_data *enc_key_pack, - krb5_data *pa_pk_as_rep) /* mallocd and RETURNED */ -{ - KRB5_PA_PK_AS_REP asRep; - SecAsn1CoderRef coder; - krb5_error_code ourRtn = 0; - CSSM_DATA der = {0, NULL}; - OSStatus ortn; - CSSM_DATA dhSignedData; - CSSM_DATA encKeyPack; - - if(SecAsn1CoderCreate(&coder)) { - return ENOMEM; - } - memset(&asRep, 0, sizeof(asRep)); - if(dh_signed_data) { - PKI_KRB_TO_CSSM_DATA(dh_signed_data, &dhSignedData); - asRep.dhSignedData = &dhSignedData; - } - if(enc_key_pack) { - PKI_KRB_TO_CSSM_DATA(enc_key_pack, &encKeyPack); - asRep.encKeyPack = &encKeyPack; - } - - ortn = SecAsn1EncodeItem(coder, &asRep, KRB5_PA_PK_AS_REPTemplate, &der); - if(ortn) { - ourRtn = ENOMEM; - goto errOut; - } - ourRtn = pkiCssmDataToKrb5Data(&der, pa_pk_as_rep); - -errOut: - SecAsn1CoderRelease(coder); - return ourRtn; -} - -/* - * Decode a KRB5_PA_PK_AS_REP. - */ -krb5_error_code krb5int_pkinit_pa_pk_as_rep_decode( - const krb5_data *pa_pk_as_rep, - krb5_data *dh_signed_data, - krb5_data *enc_key_pack) -{ - KRB5_PA_PK_AS_REP asRep; - SecAsn1CoderRef coder; - CSSM_DATA der = {pa_pk_as_rep->length, (uint8 *)pa_pk_as_rep->data}; - krb5_error_code ourRtn = 0; - - /* Decode --> KRB5_PA_PK_AS_REP */ - if(SecAsn1CoderCreate(&coder)) { - return ENOMEM; - } - memset(&asRep, 0, sizeof(asRep)); - if(SecAsn1DecodeData(coder, &der, KRB5_PA_PK_AS_REPTemplate, &asRep)) { - ourRtn = ASN1_BAD_FORMAT; - goto errOut; - } - - if(asRep.dhSignedData) { - if((ourRtn = pkiCssmDataToKrb5Data(asRep.dhSignedData, dh_signed_data))) { - goto errOut; - } - } - if(asRep.encKeyPack) { - ourRtn = pkiCssmDataToKrb5Data(asRep.encKeyPack, enc_key_pack); - } - -errOut: - SecAsn1CoderRelease(coder); - return ourRtn; -} - -#pragma mark ====== General utilities ====== - -/* - * Given a DER encoded certificate, obtain the associated IssuerAndSerialNumber. - */ -krb5_error_code krb5int_pkinit_get_issuer_serial( - const krb5_data *cert, - krb5_data *issuer_and_serial) -{ - CSSM_HANDLE cacheHand = 0; - CSSM_RETURN crtn = CSSM_OK; - CSSM_DATA certData = { cert->length, (uint8 *)cert->data }; - CSSM_HANDLE resultHand = 0; - CSSM_DATA_PTR derIssuer = NULL; - CSSM_DATA_PTR serial; - krb5_data krb_serial; - krb5_data krb_issuer; - uint32 numFields; - krb5_error_code ourRtn = 0; - - CSSM_CL_HANDLE clHand = pkiClStartup(); - if(clHand == 0) { - return CSSMERR_CSSM_ADDIN_LOAD_FAILED; - } - /* subsequent errors to errOut: */ - - crtn = CSSM_CL_CertCache(clHand, &certData, &cacheHand); - if(crtn) { - pkiCssmErr("CSSM_CL_CertCache", crtn); - ourRtn = ASN1_PARSE_ERROR; - goto errOut; - } - - /* obtain the two fields; issuer is DER encoded */ - crtn = CSSM_CL_CertGetFirstCachedFieldValue(clHand, cacheHand, - &CSSMOID_X509V1IssuerNameStd, &resultHand, &numFields, &derIssuer); - if(crtn) { - pkiCssmErr("CSSM_CL_CertGetFirstCachedFieldValue(issuer)", crtn); - ourRtn = ASN1_PARSE_ERROR; - goto errOut; - } - crtn = CSSM_CL_CertGetFirstCachedFieldValue(clHand, cacheHand, - &CSSMOID_X509V1SerialNumber, &resultHand, &numFields, &serial); - if(crtn) { - pkiCssmErr("CSSM_CL_CertGetFirstCachedFieldValue(serial)", crtn); - ourRtn = ASN1_PARSE_ERROR; - goto errOut; - } - PKI_CSSM_TO_KRB_DATA(derIssuer, &krb_issuer); - PKI_CSSM_TO_KRB_DATA(serial, &krb_serial); - ourRtn = krb5int_pkinit_issuer_serial_encode(&krb_issuer, &krb_serial, issuer_and_serial); - -errOut: - if(derIssuer) { - CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1IssuerNameStd, derIssuer); - } - if(serial) { - CSSM_CL_FreeFieldValue(clHand, &CSSMOID_X509V1SerialNumber, serial); - } - if(cacheHand) { - CSSM_CL_CertAbortCache(clHand, cacheHand); - } - if(clHand) { - pkiClDetachUnload(clHand); - } - return ourRtn; -} - -#endif /* APPLE_PKINIT */ diff --git a/src/lib/krb5/krb/pkinit_apple_cert_store.c b/src/lib/krb5/krb/pkinit_apple_cert_store.c deleted file mode 100644 index 4785b2f69..000000000 --- a/src/lib/krb5/krb/pkinit_apple_cert_store.c +++ /dev/null @@ -1,625 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of Apple Inc. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Apple Inc. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - * pkinit_apple_cert_store.c - PKINIT certificate storage/retrieval utilities, - * MAC OS X version - * - * Created 26 May 2004 by Doug Mitchell at Apple. - */ - -#if APPLE_PKINIT - -#include "pkinit_cert_store.h" -#include "pkinit_asn1.h" -#include "pkinit_apple_utils.h" -#include -#include -#include -#include -#include -#include -#include - -/* - * Client cert info is stored in preferences with this following parameters: - * - * key = kPkinitClientCertKey - * appID = kPkinitClientCertApp - * username = kCFPreferencesCurrentUser - * hostname = kCFPreferencesAnyHost - * - * The stored property list is a CFDictionary. Keys in the dictionary are - * principal names (e.g. foobar@REALM.LOCAL). - * - * Values in the dictionary are raw data containing the DER-encoded issuer and - * serial number of the certificate. - * - * When obtaining a PKINIT cert, if an entry in the CFDictionary for the specified - * principal is not found, the entry for the default will be used if it's there. - */ - -/* - * NOTE: ANSI C code requires an Apple-Custom -fconstant-cfstrings CFLAGS to - * use CFSTR in a const declaration so we just declare the C strings here. - */ -#define kPkinitClientCertKey "KRBClientCert" -#define kPkinitClientCertApp "edu.mit.Kerberos.pkinit" - -/* - * KDC cert stored in this keychain. It's linked to systemkeychain so that if - * a root process tries to unlock it, it auto-unlocks. - */ -#define KDC_KEYCHAIN "/var/db/krb5kdc/kdc.keychain" - -/* - * Given a certificate, obtain the DER-encoded issuer and serial number. Result - * is mallocd and must be freed by caller. - */ -static OSStatus pkinit_get_cert_issuer_sn( - SecCertificateRef certRef, - CSSM_DATA *issuerSerial) /* mallocd and RETURNED */ -{ - OSStatus ortn; - CSSM_DATA certData; - krb5_data INIT_KDATA(issuerSerialKrb); - krb5_data certDataKrb; - krb5_error_code krtn; - - assert(certRef != NULL); - assert(issuerSerial != NULL); - - ortn = SecCertificateGetData(certRef, &certData); - if(ortn) { - pkiCssmErr("SecCertificateGetData", ortn); - return ortn; - } - PKI_CSSM_TO_KRB_DATA(&certData, &certDataKrb); - krtn = krb5int_pkinit_get_issuer_serial(&certDataKrb, &issuerSerialKrb); - if(krtn) { - return CSSMERR_CL_INVALID_DATA; - } - PKI_KRB_TO_CSSM_DATA(&issuerSerialKrb, issuerSerial); - return noErr; -} - -/* - * Determine if specified identity's cert's issuer and serial number match the - * provided issuer and serial number. Returns nonzero on match, else returns zero. - */ -static int pkinit_issuer_sn_match( - SecIdentityRef idRef, - const CSSM_DATA *matchIssuerSerial) -{ - OSStatus ortn; - SecCertificateRef certRef = NULL; - CSSM_DATA INIT_CDATA(certIssuerSerial); - int ourRtn = 0; - - assert(idRef != NULL); - assert(matchIssuerSerial != NULL); - - /* Get this cert's issuer/serial number */ - ortn = SecIdentityCopyCertificate(idRef, &certRef); - if(ortn) { - pkiCssmErr("SecIdentityCopyCertificate", ortn); - return 0; - } - /* subsequent errors to errOut: */ - ortn = pkinit_get_cert_issuer_sn(certRef, &certIssuerSerial); - if(ortn) { - pkiCssmErr("SecIdentityCopyCertificate", ortn); - goto errOut; - } - ourRtn = pkiCompareCssmData(matchIssuerSerial, &certIssuerSerial) ? 1 : 0; -errOut: - if(certRef != NULL) { - CFRelease(certRef); - } - if(certIssuerSerial.Data != NULL) { - free(certIssuerSerial.Data); - } - return ourRtn; -} - -/* - * Search specified keychain/array/NULL (NULL meaning the default search list) for - * an Identity matching specified key usage and optional Issuer/Serial number. - * If issuer/serial is specified and no identities match, or if no identities found - * matching specified Key usage, errSecItemNotFound is returned. - * - * Caller must CFRelease a non-NULL returned idRef. - */ -static OSStatus pkinit_search_ident( - CFTypeRef keychainOrArray, - CSSM_KEYUSE keyUsage, - const CSSM_DATA *issuerSerial, /* optional */ - SecIdentityRef *foundId) /* RETURNED */ -{ - OSStatus ortn; - SecIdentityRef idRef = NULL; - SecIdentitySearchRef srchRef = NULL; - - ortn = SecIdentitySearchCreate(keychainOrArray, keyUsage, &srchRef); - if(ortn) { - pkiCssmErr("SecIdentitySearchCreate", ortn); - return ortn; - } - do { - ortn = SecIdentitySearchCopyNext(srchRef, &idRef); - if(ortn != noErr) { - break; - } - if(issuerSerial == NULL) { - /* no match needed, we're done - this is the KDC cert case */ - break; - } - else if(pkinit_issuer_sn_match(idRef, issuerSerial)) { - /* match, we're done */ - break; - } - /* finished with this one */ - CFRelease(idRef); - idRef = NULL; - } while(ortn == noErr); - - CFRelease(srchRef); - if(idRef == NULL) { - return errSecItemNotFound; - } - else { - *foundId = idRef; - return noErr; - } -} - -/* - * In Mac OS terms, get the keychain on which a given identity resides. - */ -static krb5_error_code pkinit_cert_to_db( - krb5_pkinit_signing_cert_t idRef, - krb5_pkinit_cert_db_t *dbRef) -{ - SecKeychainRef kcRef = NULL; - SecKeyRef keyRef = NULL; - OSStatus ortn; - - /* that's an identity - get the associated key's keychain */ - ortn = SecIdentityCopyPrivateKey((SecIdentityRef)idRef, &keyRef); - if(ortn) { - pkiCssmErr("SecIdentityCopyPrivateKey", ortn); - return ortn; - } - ortn = SecKeychainItemCopyKeychain((SecKeychainItemRef)keyRef, &kcRef); - if(ortn) { - pkiCssmErr("SecKeychainItemCopyKeychain", ortn); - } - else { - *dbRef = (krb5_pkinit_cert_db_t)kcRef; - } - CFRelease(keyRef); - return ortn; -} - -/* - * Obtain the CFDictionary representing this user's PKINIT client cert prefs, if it - * exists. Returns noErr or errSecItemNotFound as appropriate. - */ -static OSStatus pkinit_get_pref_dict( - CFDictionaryRef *dict) -{ - CFDictionaryRef theDict; - theDict = (CFDictionaryRef)CFPreferencesCopyValue(CFSTR(kPkinitClientCertKey), - CFSTR(kPkinitClientCertApp), kCFPreferencesCurrentUser, kCFPreferencesAnyHost); - if(theDict == NULL) { - pkiDebug("pkinit_get_pref_dict: no kPkinitClientCertKey\n"); - return errSecItemNotFound; - } - if(CFGetTypeID(theDict) != CFDictionaryGetTypeID()) { - pkiDebug("pkinit_get_pref_dict: bad kPkinitClientCertKey pref\n"); - CFRelease(theDict); - return errSecItemNotFound; - } - *dict = theDict; - return noErr; -} - -#pragma mark --- Public client side functions --- - -/* - * Obtain signing cert for specified principal. On successful return, - * caller must eventually release the cert with krb5_pkinit_release_cert(). - */ -krb5_error_code krb5_pkinit_get_client_cert( - const char *principal, /* full principal string */ - krb5_pkinit_signing_cert_t *client_cert) -{ - CFDataRef issuerSerial = NULL; - CSSM_DATA issuerSerialData; - SecIdentityRef idRef = NULL; - OSStatus ortn; - CFDictionaryRef theDict = NULL; - CFStringRef cfPrinc = NULL; - krb5_error_code ourRtn = 0; - - if(principal == NULL) { - return KRB5_PRINC_NOMATCH; - } - - /* Is there a stored preference for PKINIT certs for this user? */ - ortn = pkinit_get_pref_dict(&theDict); - if(ortn) { - return KRB5_PRINC_NOMATCH; - } - - /* Entry in the dictionary for specified principal? */ - cfPrinc = CFStringCreateWithCString(NULL, principal, - kCFStringEncodingASCII); - issuerSerial = (CFDataRef)CFDictionaryGetValue(theDict, cfPrinc); - CFRelease(cfPrinc); - if(issuerSerial == NULL) { - pkiDebug("krb5_pkinit_get_client_cert: no identity found\n"); - ourRtn = KRB5_PRINC_NOMATCH; - goto errOut; - } - if(CFGetTypeID(issuerSerial) != CFDataGetTypeID()) { - pkiDebug("krb5_pkinit_get_client_cert: bad kPkinitClientCertKey value\n"); - ourRtn = KRB5_PRINC_NOMATCH; - goto errOut; - } - - issuerSerialData.Data = (uint8 *)CFDataGetBytePtr(issuerSerial); - issuerSerialData.Length = CFDataGetLength(issuerSerial); - - /* find a cert with that issuer/serial number in default search list */ - ortn = pkinit_search_ident(NULL, CSSM_KEYUSE_SIGN | CSSM_KEYUSE_ENCRYPT, - &issuerSerialData, &idRef); - if(ortn) { - pkiDebug("krb5_pkinit_get_client_cert: no identity found!\n"); - pkiCssmErr("pkinit_search_ident", ortn); - ourRtn = KRB5_PRINC_NOMATCH; - } - else { - *client_cert = (krb5_pkinit_signing_cert_t)idRef; - } -errOut: - if(theDict) { - CFRelease(theDict); - } - return ourRtn; -} - -/* - * Determine if the specified client has a signing cert. Returns TRUE - * if so, else returns FALSE. - */ -krb5_boolean krb5_pkinit_have_client_cert( - const char *principal) /* full principal string */ -{ - krb5_pkinit_signing_cert_t signing_cert = NULL; - krb5_error_code krtn; - - krtn = krb5_pkinit_get_client_cert(principal, &signing_cert); - if(krtn) { - return FALSE; - } - if(signing_cert != NULL) { - krb5_pkinit_release_cert(signing_cert); - return TRUE; - } - else { - return FALSE; - } -} - -/* - * Store the specified certificate (or, more likely, some platform-dependent - * reference to it) as the specified principal's signing certificate. Passing - * in NULL for the client_cert has the effect of deleting the relevant entry - * in the cert storage. - */ -krb5_error_code krb5_pkinit_set_client_cert_from_signing_cert( - const char *principal, /* full principal string */ - krb5_pkinit_signing_cert_t client_cert) -{ - SecIdentityRef idRef = (SecIdentityRef)client_cert; - SecCertificateRef certRef = NULL; - OSStatus ortn; - krb5_error_code ourRtn = 0; - - if (NULL != idRef) { - if (CFGetTypeID(idRef) != SecIdentityGetTypeID()) { - ourRtn = KRB5KRB_ERR_GENERIC; - goto fin; - } - /* Get the cert */ - ortn = SecIdentityCopyCertificate(idRef, &certRef); - if (ortn) { - pkiCssmErr("SecIdentityCopyCertificate", ortn); - ourRtn = KRB5KRB_ERR_GENERIC; - goto fin; - } - } - ourRtn = krb5_pkinit_set_client_cert(principal, (krb5_pkinit_cert_t)certRef); -fin: - if (certRef) - CFRelease(certRef); - return ourRtn; -} - - -/* - * Store the specified certificate (or, more likely, some platform-dependent - * reference to it) as the specified principal's certificate. Passing - * in NULL for the client_cert has the effect of deleting the relevant entry - * in the cert storage. - */ -krb5_error_code krb5_pkinit_set_client_cert( - const char *principal, /* full principal string */ - krb5_pkinit_cert_t client_cert) -{ - SecCertificateRef certRef = (SecCertificateRef)client_cert; - OSStatus ortn; - CSSM_DATA issuerSerial = {0, NULL}; - CFDataRef cfIssuerSerial = NULL; - CFDictionaryRef existDict = NULL; - CFMutableDictionaryRef newDict = NULL; - CFStringRef keyStr = NULL; - krb5_error_code ourRtn = 0; - - if(certRef != NULL) { - if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) { - return KRB5KRB_ERR_GENERIC; - } - - /* Cook up DER-encoded issuer/serial number */ - ortn = pkinit_get_cert_issuer_sn(certRef, &issuerSerial); - if(ortn) { - ourRtn = KRB5KRB_ERR_GENERIC; - goto errOut; - } - } - - /* - * Obtain the existing pref for kPkinitClientCertKey as a CFDictionary, or - * cook up a new one. - */ - ortn = pkinit_get_pref_dict(&existDict); - if(ortn == noErr) { - /* dup to a mutable dictionary */ - newDict = CFDictionaryCreateMutableCopy(NULL, 0, existDict); - } - else { - if(certRef == NULL) { - /* no existing entry, nothing to delete, we're done */ - return 0; - } - newDict = CFDictionaryCreateMutable(NULL, 0, - &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - } - if(newDict == NULL) { - ourRtn = ENOMEM; - goto errOut; - } - - /* issuer / serial number ==> that dictionary */ - keyStr = CFStringCreateWithCString(NULL, principal, kCFStringEncodingASCII); - if(certRef == NULL) { - CFDictionaryRemoveValue(newDict, keyStr); - } - else { - cfIssuerSerial = CFDataCreate(NULL, issuerSerial.Data, issuerSerial.Length); - CFDictionarySetValue(newDict, keyStr, cfIssuerSerial); - } - - /* dictionary ==> prefs */ - CFPreferencesSetValue(CFSTR(kPkinitClientCertKey), newDict, - CFSTR(kPkinitClientCertApp), kCFPreferencesCurrentUser, kCFPreferencesAnyHost); - if(CFPreferencesSynchronize(CFSTR(kPkinitClientCertApp), kCFPreferencesCurrentUser, - kCFPreferencesAnyHost)) { - ourRtn = 0; - } - else { - ourRtn = EACCES; /* any better ideas? */ - } -errOut: - if(cfIssuerSerial) { - CFRelease(cfIssuerSerial); - } - if(issuerSerial.Data) { - free(issuerSerial.Data); - } - if(existDict) { - CFRelease(existDict); - } - if(newDict) { - CFRelease(newDict); - } - if(keyStr) { - CFRelease(keyStr); - } - return ourRtn; -} - -/* - * Obtain a reference to the client's cert database. Specify either principal - * name or client_cert as obtained from krb5_pkinit_get_client_cert(). - */ -krb5_error_code krb5_pkinit_get_client_cert_db( - const char *principal, /* full principal string */ - krb5_pkinit_signing_cert_t client_cert, /* optional, from krb5_pkinit_get_client_cert() */ - krb5_pkinit_cert_db_t *client_cert_db)/* RETURNED */ -{ - krb5_error_code krtn; - krb5_pkinit_signing_cert_t local_cert; - - assert((client_cert != NULL) || (principal != NULL)); - if(client_cert == NULL) { - /* caller didn't provide, look it up */ - krtn = krb5_pkinit_get_client_cert(principal, &local_cert); - if(krtn) { - return krtn; - } - } - else { - /* easy case */ - local_cert = client_cert; - } - krtn = pkinit_cert_to_db(local_cert, client_cert_db); - if(client_cert == NULL) { - krb5_pkinit_release_cert(local_cert); - } - return krtn; -} - -#pragma mark --- Public server side functions --- - -/* - * Obtain the KDC signing cert, with optional CA and specific cert specifiers. - * CAs and cert specifiers are in the form of DER-encoded issuerAndSerialNumbers. - * - * The client_spec argument is typically provided by the client as kdcPkId. - */ -krb5_error_code krb5_pkinit_get_kdc_cert( - krb5_ui_4 num_trusted_CAs, /* sizeof *trusted_CAs */ - krb5_data *trusted_CAs, /* optional */ - krb5_data *client_spec, /* optional */ - krb5_pkinit_signing_cert_t *kdc_cert) -{ - SecIdentityRef idRef = NULL; - OSStatus ortn; - krb5_error_code ourRtn = 0; - - /* OS X: trusted_CAs and client_spec ignored */ - - ortn = SecIdentityCopySystemIdentity(kSecIdentityDomainKerberosKDC, - &idRef, NULL); - if(ortn) { - pkiCssmErr("SecIdentityCopySystemIdentity", ortn); - return KRB5_PRINC_NOMATCH; - } - *kdc_cert = (krb5_pkinit_signing_cert_t)idRef; - return ourRtn; -} - -/* - * Obtain a reference to the KDC's cert database. - */ -krb5_error_code krb5_pkinit_get_kdc_cert_db( - krb5_pkinit_cert_db_t *kdc_cert_db) -{ - krb5_pkinit_signing_cert_t kdcCert = NULL; - krb5_error_code krtn; - - krtn = krb5_pkinit_get_kdc_cert(0, NULL, NULL, &kdcCert); - if(krtn) { - return krtn; - } - krtn = pkinit_cert_to_db(kdcCert, kdc_cert_db); - krb5_pkinit_release_cert(kdcCert); - return krtn; -} - -/* - * Release certificate references obtained via krb5_pkinit_get_client_cert() and - * krb5_pkinit_get_kdc_cert(). - */ -void krb5_pkinit_release_cert( - krb5_pkinit_signing_cert_t cert) -{ - if(cert == NULL) { - return; - } - CFRelease((CFTypeRef)cert); -} - -/* - * Release database references obtained via krb5_pkinit_get_client_cert_db() and - * krb5_pkinit_get_kdc_cert_db(). - */ -extern void krb5_pkinit_release_cert_db( - krb5_pkinit_cert_db_t cert_db) -{ - if(cert_db == NULL) { - return; - } - CFRelease((CFTypeRef)cert_db); -} - - -/* - * Obtain a mallocd C-string representation of a certificate's SHA1 digest. - * Only error is a NULL return indicating memory failure. - * Caller must free the returned string. - */ -char *krb5_pkinit_cert_hash_str( - const krb5_data *cert) -{ - CC_SHA1_CTX ctx; - char *outstr; - char *cpOut; - unsigned char digest[CC_SHA1_DIGEST_LENGTH]; - unsigned dex; - - assert(cert != NULL); - CC_SHA1_Init(&ctx); - CC_SHA1_Update(&ctx, cert->data, cert->length); - CC_SHA1_Final(digest, &ctx); - - outstr = (char *)malloc((2 * CC_SHA1_DIGEST_LENGTH) + 1); - if(outstr == NULL) { - return NULL; - } - cpOut = outstr; - for(dex=0; dexdata = NULL; - kdc_cert->length = 0; - return 0; -} - -#endif /* APPLE_PKINIT */ diff --git a/src/lib/krb5/krb/pkinit_apple_client.c b/src/lib/krb5/krb/pkinit_apple_client.c deleted file mode 100644 index 6183d8b15..000000000 --- a/src/lib/krb5/krb/pkinit_apple_client.c +++ /dev/null @@ -1,263 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of Apple Inc. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Apple Inc. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -/* - * pkinit_apple_client.c - Client side routines for PKINIT, Mac OS X version - * - * Created 20 May 2004 by Doug Mitchell at Apple. - */ - -#if APPLE_PKINIT - -#include "pkinit_client.h" -#include "pkinit_asn1.h" -#include "pkinit_apple_utils.h" -#include "pkinit_cms.h" -#include -#include -#include -#include -#include - -/* - * Create a PA-PK-AS-REQ message. - */ -krb5_error_code krb5int_pkinit_as_req_create( - krb5_context context, - krb5_timestamp kctime, - krb5_int32 cusec, /* microseconds */ - krb5_ui_4 nonce, - const krb5_checksum *cksum, - krb5_pkinit_signing_cert_t client_cert, /* required */ - const krb5_data *trusted_CAs, /* optional list of CA certs */ - krb5_ui_4 num_trusted_CAs, - const krb5_data *kdc_cert, /* optional KDC cert */ - krb5_data *as_req) /* mallocd and RETURNED */ -{ - 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; - - /* issuer/serial numbers for trusted_CAs and kdc_cert, if we have them */ - krb5_data *ca_issuer_sn = NULL; /* issuer/serial_num for trusted_CAs */ - krb5_data kdc_issuer_sn = {0}; /* issuer/serial_num for kdc_cert */ - krb5_data *kdc_issuer_sn_p = NULL; - - /* optional platform-dependent CMS algorithm preference */ - krtn = krb5int_pkinit_get_cms_types(&cms_types, &num_cms_types); - if(krtn) { - return krtn; - } - - /* encode the core authPack */ - krtn = krb5int_pkinit_auth_pack_encode(kctime, cusec, nonce, cksum, - cms_types, num_cms_types, - &auth_pack); - if(krtn) { - goto errOut; - } - - /* package the AuthPack up in a SignedData inside a ContentInfo */ - krtn = krb5int_pkinit_create_cms_msg(&auth_pack, - client_cert, - NULL, /* recip_cert */ - ECT_PkAuthData, - 0, NULL, /* cms_types */ - &content_info); - if(krtn) { - goto errOut; - } - - /* if we have trusted_CAs, get issuer/serials */ - 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 -#include -#include -#include -#include -#include -#include - -/* - * Custom OIDS to specify as eContentType - */ -#define OID_PKINIT 0x2B, 6, 1, 5, 2, 3 -#define OID_PKINIT_LEN 6 - -static const uint8 OID_PKINIT_AUTH_DATA[] = {OID_PKINIT, 1}; -static const uint8 OID_PKINIT_RKEY_DATA[] = {OID_PKINIT, 3}; - -/* these may go public so keep these symbols private */ -static const CSSM_OID _CSSMOID_PKINIT_AUTH_DATA = -{OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_AUTH_DATA}; -static const CSSM_OID _CSSMOID_PKINIT_RKEY_DATA = -{OID_PKINIT_LEN+1, (uint8 *)OID_PKINIT_RKEY_DATA}; - - -#pragma mark ----- CMS utilities ---- - -#define CFRELEASE(cf) if(cf) { CFRelease(cf); } - -/* - * Convert platform-specific cert/signature status to krb5int_cert_sig_status. - */ -static krb5int_cert_sig_status pkiCertSigStatus( - OSStatus certStatus) -{ - switch(certStatus) { - case CSSM_OK: - return pki_cs_good; - case CSSMERR_CSP_VERIFY_FAILED: - return pki_cs_sig_verify_fail; - case CSSMERR_TP_NOT_TRUSTED: - return pki_cs_no_root; - case CSSMERR_TP_INVALID_ANCHOR_CERT: - return pki_cs_unknown_root; - case CSSMERR_TP_CERT_EXPIRED: - return pki_cs_expired; - case CSSMERR_TP_CERT_NOT_VALID_YET: - return pki_cs_not_valid_yet; - case CSSMERR_TP_CERT_REVOKED: - return pki_cs_revoked; - case KRB5_KDB_UNAUTH: - return pki_cs_untrusted; - case CSSMERR_TP_INVALID_CERTIFICATE: - return pki_cs_bad_leaf; - default: - return pki_cs_other_err; - } -} - -/* - * Infer krb5int_cert_sig_status from CMSSignerStatus and a CSSM TO - * cert veriofy result code (obtained via the certVerifyResultCode argument - * in CMSDecoderCopySignerStatus()). - */ -static krb5int_cert_sig_status pkiInferSigStatus( - CMSSignerStatus cms_status, - OSStatus tp_status) -{ - switch(cms_status) { - case kCMSSignerUnsigned: - return pki_not_signed; - case kCMSSignerValid: - return pki_cs_good; - case kCMSSignerNeedsDetachedContent: - return pki_bad_cms; - case kCMSSignerInvalidSignature: - return pki_cs_sig_verify_fail; - case kCMSSignerInvalidCert: - /* proceed with TP status */ - break; - default: - return pki_cs_other_err; - } - - /* signature good, infer end status from TP verify */ - return pkiCertSigStatus(tp_status); -} - -/* - * Cook up a SecCertificateRef from a krb5_data. - */ -static OSStatus pkiKrb5DataToSecCert( - const krb5_data *rawCert, - SecCertificateRef *secCert) /* RETURNED */ -{ - CSSM_DATA certData; - OSStatus ortn; - - assert((rawCert != NULL) && (secCert != NULL)); - - certData.Data = (uint8 *)rawCert->data; - certData.Length = rawCert->length; - ortn = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, - CSSM_CERT_ENCODING_DER, secCert); - if(ortn) { - pkiCssmErr("SecCertificateCreateFromData", ortn); - } - return ortn; -} - -/* - * Convert CFArray of SecCertificateRefs to a mallocd array of krb5_datas. - */ -static krb5_error_code pkiCertArrayToKrb5Data( - CFArrayRef cf_certs, - unsigned *num_all_certs, - krb5_data **all_certs) -{ - CFIndex num_certs; - krb5_data *allCerts = NULL; - krb5_error_code krtn = 0; - CFIndex dex; - - if(cf_certs == NULL) { - *all_certs = NULL; - return 0; - } - num_certs = CFArrayGetCount(cf_certs); - *num_all_certs = (unsigned)num_certs; - if(num_certs == 0) { - *all_certs = NULL; - return 0; - } - allCerts = (krb5_data *)malloc(sizeof(krb5_data) * num_certs); - if(allCerts == NULL) { - return ENOMEM; - } - for(dex=0; dexdata, content->length, - &cf_content); - if(ortn) { - pkiCssmErr("CMSEncode", ortn); - krtn = KRB5_CRYPTO_INTERNAL; - goto errOut; - } - krtn = pkiCfDataToKrb5Data(cf_content, content_info); -errOut: - CFRELEASE(sec_recip); - CFRELEASE(cf_content); - return krtn; -} - -#pragma mark ----- Generalized parse ContentInfo ---- - -/* - * Parse a ContentInfo as best we can. All return fields are optional. - * If signer_cert_status is NULL on entry, NO signature or cert evaluation - * will be performed. - */ -krb5_error_code krb5int_pkinit_parse_cms_msg( - const krb5_data *content_info, - krb5_pkinit_cert_db_t cert_db, /* may be required for SignedData */ - krb5_boolean is_client_msg, /* TRUE : msg is from client */ - krb5_boolean *is_signed, /* RETURNED */ - krb5_boolean *is_encrypted, /* RETURNED */ - krb5_data *raw_data, /* RETURNED */ - krb5int_cms_content_type *inner_content_type,/* Returned, ContentType of */ - /* EncapsulatedData */ - krb5_data *signer_cert, /* RETURNED */ - krb5int_cert_sig_status *signer_cert_status,/* RETURNED */ - unsigned *num_all_certs, /* size of *all_certs RETURNED */ - krb5_data **all_certs) /* entire cert chain RETURNED */ -{ - SecPolicySearchRef policy_search = NULL; - SecPolicyRef policy = NULL; - OSStatus ortn; - krb5_error_code krtn = 0; - CMSDecoderRef decoder = NULL; - size_t num_signers; - CMSSignerStatus signer_status; - OSStatus cert_verify_status; - CFArrayRef cf_all_certs = NULL; - int msg_is_signed = 0; - - if(content_info == NULL) { - pkiDebug("krb5int_pkinit_parse_cms_msg: no ContentInfo\n"); - return KRB5_CRYPTO_INTERNAL; - } - - ortn = CMSDecoderCreate(&decoder); - if(ortn) { - return ENOMEM; - } - ortn = CMSDecoderUpdateMessage(decoder, content_info->data, content_info->length); - if(ortn) { - /* no verify yet, must be bad message */ - krtn = KRB5_PARSE_MALFORMED; - goto errOut; - } - ortn = CMSDecoderFinalizeMessage(decoder); - if(ortn) { - pkiCssmErr("CMSDecoderFinalizeMessage", ortn); - krtn = KRB5_PARSE_MALFORMED; - goto errOut; - } - - /* expect zero or one signers */ - ortn = CMSDecoderGetNumSigners(decoder, &num_signers); - switch(num_signers) { - case 0: - msg_is_signed = 0; - break; - case 1: - msg_is_signed = 1; - break; - default: - krtn = KRB5_PARSE_MALFORMED; - goto errOut; - } - - /* - * We need a cert verify policy even if we're not actually evaluating - * the cert due to requirements in libsecurity_smime. - */ - ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3, - is_client_msg ? &CSSMOID_APPLE_TP_PKINIT_CLIENT : &CSSMOID_APPLE_TP_PKINIT_SERVER, - NULL, &policy_search); - if(ortn) { - pkiCssmErr("SecPolicySearchCreate", ortn); - krtn = KRB5_CRYPTO_INTERNAL; - goto errOut; - } - ortn = SecPolicySearchCopyNext(policy_search, &policy); - if(ortn) { - pkiCssmErr("SecPolicySearchCopyNext", ortn); - krtn = KRB5_CRYPTO_INTERNAL; - goto errOut; - } - - /* get some basic status that doesn't need heavyweight evaluation */ - if(msg_is_signed) { - if(is_signed) { - *is_signed = TRUE; - } - if(inner_content_type) { - CSSM_OID ec_oid = {0, NULL}; - CFDataRef ec_data = NULL; - - krb5int_cms_content_type ctype; - - ortn = CMSDecoderCopyEncapsulatedContentType(decoder, &ec_data); - if(ortn || (ec_data == NULL)) { - pkiCssmErr("CMSDecoderCopyEncapsulatedContentType", ortn); - krtn = KRB5_CRYPTO_INTERNAL; - goto errOut; - } - ec_oid.Data = (uint8 *)CFDataGetBytePtr(ec_data); - ec_oid.Length = CFDataGetLength(ec_data); - if(pkiCompareCssmData(&ec_oid, &CSSMOID_PKCS7_Data)) { - ctype = ECT_Data; - } - else if(pkiCompareCssmData(&ec_oid, &CSSMOID_PKCS7_SignedData)) { - ctype = ECT_SignedData; - } - else if(pkiCompareCssmData(&ec_oid, &CSSMOID_PKCS7_EnvelopedData)) { - ctype = ECT_EnvelopedData; - } - else if(pkiCompareCssmData(&ec_oid, &CSSMOID_PKCS7_EncryptedData)) { - ctype = ECT_EncryptedData; - } - else if(pkiCompareCssmData(&ec_oid, &_CSSMOID_PKINIT_AUTH_DATA)) { - ctype = ECT_PkAuthData; - } - else if(pkiCompareCssmData(&ec_oid, &_CSSMOID_PKINIT_RKEY_DATA)) { - ctype = ECT_PkReplyKeyKata; - } - else { - ctype = ECT_Other; - } - *inner_content_type = ctype; - CFRelease(ec_data); - } - - /* - * Get SignedData's certs if the caller wants them - */ - if(all_certs) { - ortn = CMSDecoderCopyAllCerts(decoder, &cf_all_certs); - if(ortn) { - pkiCssmErr("CMSDecoderCopyAllCerts", ortn); - krtn = KRB5_CRYPTO_INTERNAL; - goto errOut; - } - krtn = pkiCertArrayToKrb5Data(cf_all_certs, num_all_certs, all_certs); - if(krtn) { - goto errOut; - } - } - - /* optional signer cert */ - if(signer_cert) { - SecCertificateRef sec_signer_cert = NULL; - CSSM_DATA cert_data; - - ortn = CMSDecoderCopySignerCert(decoder, 0, &sec_signer_cert); - if(ortn) { - /* should never happen if it's signed */ - pkiCssmErr("CMSDecoderCopySignerStatus", ortn); - krtn = KRB5_CRYPTO_INTERNAL; - goto errOut; - } - ortn = SecCertificateGetData(sec_signer_cert, &cert_data); - if(ortn) { - pkiCssmErr("SecCertificateGetData", ortn); - CFRelease(sec_signer_cert); - krtn = KRB5_CRYPTO_INTERNAL; - goto errOut; - } - krtn = pkiDataToKrb5Data(cert_data.Data, cert_data.Length, signer_cert); - CFRelease(sec_signer_cert); - if(krtn) { - goto errOut; - } - } - } - else { - /* not signed */ - if(is_signed) { - *is_signed = FALSE; - } - if(inner_content_type) { - *inner_content_type = ECT_Other; - } - if(signer_cert) { - signer_cert->data = NULL; - signer_cert->length = 0; - } - if(signer_cert_status) { - *signer_cert_status = pki_not_signed; - } - if(num_all_certs) { - *num_all_certs = 0; - } - if(all_certs) { - *all_certs = NULL; - } - } - if(is_encrypted) { - Boolean bencr; - ortn = CMSDecoderIsContentEncrypted(decoder, &bencr); - if(ortn) { - pkiCssmErr("CMSDecoderCopySignerStatus", ortn); - krtn = KRB5_CRYPTO_INTERNAL; - goto errOut; - } - *is_encrypted = bencr ? TRUE : FALSE; - } - - /* - * Verify signature and cert. The actual verify operation is optional, - * per our signer_cert_status argument, but we do this anyway if we need - * to get the signer cert. - */ - if((signer_cert_status != NULL) || (signer_cert != NULL)) { - - ortn = CMSDecoderCopySignerStatus(decoder, - 0, /* signerIndex */ - policy, - signer_cert_status ? TRUE : FALSE, /* evaluateSecTrust */ - &signer_status, - NULL, /* secTrust - not needed */ - &cert_verify_status); - if(ortn) { - /* gross error - subsequent processing impossible */ - pkiCssmErr("CMSDecoderCopySignerStatus", ortn); - krtn = KRB5_PARSE_MALFORMED; - goto errOut; - } - } - /* obtain & return status */ - if(signer_cert_status) { - *signer_cert_status = pkiInferSigStatus(signer_status, cert_verify_status); - } - - /* finally, the payload */ - if(raw_data) { - CFDataRef cf_content = NULL; - - ortn = CMSDecoderCopyContent(decoder, &cf_content); - if(ortn) { - pkiCssmErr("CMSDecoderCopyContent", ortn); - krtn = KRB5_PARSE_MALFORMED; - goto errOut; - } - krtn = pkiCfDataToKrb5Data(cf_content, raw_data); - CFRELEASE(cf_content); - } -errOut: - CFRELEASE(policy_search); - CFRELEASE(policy); - CFRELEASE(cf_all_certs); - CFRELEASE(decoder); - return krtn; -} - -krb5_error_code krb5int_pkinit_get_cms_types( - krb5int_algorithm_id **supported_cms_types, /* RETURNED */ - krb5_ui_4 *num_supported_cms_types) /* RETURNED */ -{ - /* no preference */ - *supported_cms_types = NULL; - *num_supported_cms_types = 0; - return 0; -} - -krb5_error_code krb5int_pkinit_free_cms_types( - krb5int_algorithm_id *supported_cms_types, - krb5_ui_4 num_supported_cms_types) -{ - /* - * We don't return anything from krb5int_pkinit_get_cms_types(), and - * if we did, it would be a pointer to a statically declared array, - * so this is a nop. - */ - return 0; -} - -#endif /* APPLE_PKINIT */ diff --git a/src/lib/krb5/krb/pkinit_apple_utils.c b/src/lib/krb5/krb/pkinit_apple_utils.c deleted file mode 100644 index 83b592218..000000000 --- a/src/lib/krb5/krb/pkinit_apple_utils.c +++ /dev/null @@ -1,434 +0,0 @@ -/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright (c) 2004-2008 Apple Inc. All Rights Reserved. - * - * Export of this software from the United States of America may require - * a specific license from the United States Government. It is the - * responsibility of any person or organization contemplating export to - * obtain such a license before exporting. - * - * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and - * distribute this software and its documentation for any purpose and - * without fee is hereby granted, provided that the above copyright - * notice appear in all copies and that both that copyright notice and - * this permission notice appear in supporting documentation, and that - * the name of Apple Inc. not be used in advertising or publicity pertaining - * to distribution of the software without specific, written prior - * permission. Apple Inc. makes no representations about the suitability of - * this software for any purpose. It is provided "as is" without express - * or implied warranty. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -/* - * pkinit_apple_utils.c - PKINIT utilities, Mac OS X version - * - * Created 19 May 2004 by Doug Mitchell at Apple. - */ - -#if APPLE_PKINIT - -#include "pkinit_apple_utils.h" -#include "pkinit_asn1.h" -#include -#include -#include -#include -#include -#include -#include - -/* - * Cruft needed to attach to a module - */ -static CSSM_VERSION vers = {2, 0}; -static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }}; - -/* - * Standard app-level memory functions required by CDSA. - */ -static void * cuAppMalloc (CSSM_SIZE size, void *allocRef) { - return( malloc(size) ); -} - -static void cuAppFree (void *mem_ptr, void *allocRef) { - free(mem_ptr); - return; -} - -static void * cuAppRealloc (void *ptr, CSSM_SIZE size, void *allocRef) { - return( realloc( ptr, size ) ); -} - -static void * cuAppCalloc (uint32 num, CSSM_SIZE size, void *allocRef) { - return( calloc( num, size ) ); -} - -static CSSM_API_MEMORY_FUNCS memFuncs = { - cuAppMalloc, - cuAppFree, - cuAppRealloc, - cuAppCalloc, - NULL -}; - -/* - * Init CSSM; returns CSSM_FALSE on error. Reusable. - */ -static CSSM_BOOL cssmInitd = CSSM_FALSE; - -static CSSM_BOOL cuCssmStartup() -{ - CSSM_RETURN crtn; - CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE; - - if(cssmInitd) { - return CSSM_TRUE; - } - crtn = CSSM_Init (&vers, - CSSM_PRIVILEGE_SCOPE_NONE, - &testGuid, - CSSM_KEY_HIERARCHY_NONE, - &pvcPolicy, - NULL /* reserved */); - if(crtn != CSSM_OK) - { - return CSSM_FALSE; - } - else { - cssmInitd = CSSM_TRUE; - return CSSM_TRUE; - } -} - -CSSM_CL_HANDLE pkiClStartup(void) -{ - CSSM_CL_HANDLE clHand; - CSSM_RETURN crtn; - - if(cuCssmStartup() == CSSM_FALSE) { - return 0; - } - crtn = CSSM_ModuleLoad(&gGuidAppleX509CL, - CSSM_KEY_HIERARCHY_NONE, - NULL, /* eventHandler */ - NULL); /* AppNotifyCallbackCtx */ - if(crtn) { - return 0; - } - crtn = CSSM_ModuleAttach (&gGuidAppleX509CL, - &vers, - &memFuncs, /* memFuncs */ - 0, /* SubserviceID */ - CSSM_SERVICE_CL, /* SubserviceFlags - Where is this used? */ - 0, /* AttachFlags */ - CSSM_KEY_HIERARCHY_NONE, - NULL, /* FunctionTable */ - 0, /* NumFuncTable */ - NULL, /* reserved */ - &clHand); - if(crtn) { - return 0; - } - else { - return clHand; - } -} - -CSSM_RETURN pkiClDetachUnload( - CSSM_CL_HANDLE clHand) -{ - CSSM_RETURN crtn = CSSM_ModuleDetach(clHand); - if(crtn) { - return crtn; - } - return CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL); -} - -/* - * CSSM_DATA <--> krb5_ui_4 - */ -krb5_error_code pkiDataToInt( - const CSSM_DATA *cdata, - krb5_int32 *i) /* RETURNED */ -{ - krb5_ui_4 len; - krb5_int32 rtn = 0; - krb5_ui_4 dex; - uint8 *cp = NULL; - - if((cdata->Length == 0) || (cdata->Data == NULL)) { - *i = 0; - return 0; - } - len = cdata->Length; - if(len > sizeof(krb5_int32)) { - return ASN1_BAD_LENGTH; - } - - cp = cdata->Data; - for(dex=0; dexData[len - 1]; - for(i=0; i>= 8; - } - return 0; -} - -/* - * raw data --> krb5_data - */ -krb5_error_code pkiDataToKrb5Data( - const void *data, - unsigned dataLen, - krb5_data *kd) -{ - assert(data != NULL); - assert(kd != NULL); - kd->data = (char *)malloc(dataLen); - if(kd->data == NULL) { - return ENOMEM; - } - kd->length = dataLen; - memmove(kd->data, data, dataLen); - return 0; -} - -/* - * CSSM_DATA <--> krb5_data - * - * CSSM_DATA data is managed by a SecAsn1CoderRef; krb5_data data is mallocd. - * - * Both return nonzero on error. - */ -krb5_error_code pkiCssmDataToKrb5Data( - const CSSM_DATA *cd, - krb5_data *kd) -{ - assert(cd != NULL); - return pkiDataToKrb5Data(cd->Data, cd->Length, kd); -} - -krb5_error_code pkiKrb5DataToCssm( - const krb5_data *kd, - CSSM_DATA *cd, - SecAsn1CoderRef coder) -{ - assert((cd != NULL) && (kd != NULL)); - if(SecAsn1AllocCopy(coder, kd->data, kd->length, cd)) { - return ENOMEM; - } - return 0; -} - -/* - * CFDataRef --> krb5_data, mallocing the destination contents. - */ -krb5_error_code pkiCfDataToKrb5Data( - CFDataRef cfData, - krb5_data *kd) /* content mallocd and RETURNED */ -{ - return pkiDataToKrb5Data(CFDataGetBytePtr(cfData), - CFDataGetLength(cfData), kd); -} - -krb5_boolean pkiCompareCssmData( - const CSSM_DATA *d1, - const CSSM_DATA *d2) -{ - if((d1 == NULL) || (d2 == NULL)) { - return FALSE; - } - if(d1->Length != d2->Length) { - return FALSE; - } - if(memcmp(d1->Data, d2->Data, d1->Length)) { - return FALSE; - } - else { - return TRUE; - } -} - -/* - * krb5_timestamp --> a mallocd string in generalized format - */ -krb5_error_code pkiKrbTimestampToStr( - krb5_timestamp kts, - char **str) /* mallocd and RETURNED */ -{ - char *outStr = NULL; - time_t gmt_time = kts; - struct tm *utc = gmtime(&gmt_time); - if (utc == NULL || - utc->tm_year > 8099 || utc->tm_mon > 11 || - utc->tm_mday > 31 || utc->tm_hour > 23 || - utc->tm_min > 59 || utc->tm_sec > 59) { - return ASN1_BAD_GMTIME; - } - if (asprintf(&outStr, "%04d%02d%02d%02d%02d%02dZ", - utc->tm_year + 1900, utc->tm_mon + 1, - utc->tm_mday, utc->tm_hour, utc->tm_min, utc->tm_sec) < 0) { - return ENOMEM; - } - *str = outStr; - return 0; -} - -krb5_error_code pkiTimeStrToKrbTimestamp( - const char *str, - unsigned len, - krb5_timestamp *kts) /* RETURNED */ -{ - char szTemp[5]; - unsigned x; - unsigned i; - char *cp; - struct tm tmp; - time_t t; - - if(len != 15) { - return ASN1_BAD_LENGTH; - } - - if((str == NULL) || (kts == NULL)) { - return KRB5_CRYPTO_INTERNAL; - } - - cp = (char *)str; - memset(&tmp, 0, sizeof(tmp)); - - /* check that all characters except last are digits */ - for(i=0; i<(len - 1); i++) { - if ( !(isdigit(cp[i])) ) { - return ASN1_BAD_TIMEFORMAT; - } - } - - /* check last character is a 'Z' */ - if(cp[len - 1] != 'Z' ) { - return ASN1_BAD_TIMEFORMAT; - } - - /* YEAR */ - szTemp[0] = *cp++; - szTemp[1] = *cp++; - szTemp[2] = *cp++; - szTemp[3] = *cp++; - szTemp[4] = '\0'; - x = atoi( szTemp ); - /* by definition - tm_year is year - 1900 */ - tmp.tm_year = x - 1900; - - /* MONTH */ - szTemp[0] = *cp++; - szTemp[1] = *cp++; - szTemp[2] = '\0'; - x = atoi( szTemp ); - /* in the string, months are from 1 to 12 */ - if((x > 12) || (x <= 0)) { - return ASN1_BAD_TIMEFORMAT; - } - /* in a tm, 0 to 11 */ - tmp.tm_mon = x - 1; - - /* DAY */ - szTemp[0] = *cp++; - szTemp[1] = *cp++; - szTemp[2] = '\0'; - x = atoi( szTemp ); - /* 1..31 */ - if((x > 31) || (x <= 0)) { - return ASN1_BAD_TIMEFORMAT; - } - tmp.tm_mday = x; - - /* HOUR */ - szTemp[0] = *cp++; - szTemp[1] = *cp++; - szTemp[2] = '\0'; - x = atoi( szTemp ); - if((x > 23) || (x < 0)) { - return ASN1_BAD_TIMEFORMAT; - } - tmp.tm_hour = x; - - /* MINUTE */ - szTemp[0] = *cp++; - szTemp[1] = *cp++; - szTemp[2] = '\0'; - x = atoi( szTemp ); - if((x > 59) || (x < 0)) { - return ASN1_BAD_TIMEFORMAT; - } - tmp.tm_min = x; - - /* SECOND */ - szTemp[0] = *cp++; - szTemp[1] = *cp++; - szTemp[2] = '\0'; - x = atoi( szTemp ); - if((x > 59) || (x < 0)) { - return ASN1_BAD_TIMEFORMAT; - } - tmp.tm_sec = x; - t = timegm(&tmp); - if(t == -1) { - return ASN1_BAD_TIMEFORMAT; - } - *kts = t; - return 0; -} - -/* - * How many items in a NULL-terminated array of pointers? - */ -unsigned pkiNssArraySize( - const void **array) -{ - unsigned count = 0; - if (array) { - while (*array++) { - count++; - } - } - return count; -} - -#endif /* APPLE_PKINIT */ diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c index 5bc83086a..81c508d53 100644 --- a/src/lib/krb5/krb/preauth2.c +++ b/src/lib/krb5/krb/preauth2.c @@ -31,10 +31,6 @@ */ #include "k5-int.h" -#if APPLE_PKINIT -#include "pkinit_client.h" -#include "pkinit_cert_store.h" -#endif /* APPLE_PKINIT */ #include "osconf.h" #include #include "int-proto.h" @@ -604,320 +600,6 @@ pa_fx_cookie(krb5_context context, krb5_kdc_req *request, return 0; } -#if APPLE_PKINIT -/* - * PKINIT. One function to generate AS-REQ, one to parse AS-REP - */ -#define PKINIT_DEBUG 0 -#if PKINIT_DEBUG -#define kdcPkinitDebug(args...) printf(args) -#else -#define kdcPkinitDebug(args...) -#endif - -static krb5_error_code -pa_pkinit_gen_req(krb5_context context, - krb5_kdc_req *request, - krb5_pa_data *in_padata, - krb5_pa_data **out_padata, - krb5_data *salt, - krb5_data *s2kparams, - krb5_enctype *etype, - krb5_keyblock *as_key, - krb5_prompter_fct prompter, - void *prompter_data, - krb5_gic_get_as_key_fct gak_fct, - void *gak_data) -{ - krb5_error_code krtn; - krb5_data out_data = {0, 0, NULL}; - krb5_timestamp kctime = 0; - krb5_int32 cusec = 0; - krb5_ui_4 nonce = 0; - krb5_checksum cksum; - krb5_pkinit_signing_cert_t client_cert; - krb5_data *der_req = NULL; - char *client_principal = NULL; - char *server_principal = NULL; - unsigned char nonce_bytes[4]; - krb5_data nonce_data = {0, 4, (char *)nonce_bytes}; - int dex; - - /* - * Trusted CA list and specific KC cert optionally obtained via - * krb5_pkinit_get_server_certs(). All are DER-encoded certs. - */ - krb5_data *trusted_CAs = NULL; - krb5_ui_4 num_trusted_CAs; - krb5_data kdc_cert = {0}; - - kdcPkinitDebug("pa_pkinit_gen_req\n"); - - /* If we don't have a client cert, we're done */ - if(request->client == NULL) { - kdcPkinitDebug("No request->client; aborting PKINIT\n"); - return KRB5KDC_ERR_PREAUTH_FAILED; - } - krtn = krb5_unparse_name(context, request->client, &client_principal); - if(krtn) { - return krtn; - } - krtn = krb5_pkinit_get_client_cert(client_principal, &client_cert); - free(client_principal); - if(krtn) { - kdcPkinitDebug("No client cert; aborting PKINIT\n"); - return krtn; - } - - /* optional platform-dependent CA list and KDC cert */ - krtn = krb5_unparse_name(context, request->server, &server_principal); - if(krtn) { - goto cleanup; - } - krtn = krb5_pkinit_get_server_certs(client_principal, server_principal, - &trusted_CAs, &num_trusted_CAs, &kdc_cert); - if(krtn) { - goto cleanup; - } - - /* checksum of the encoded KDC-REQ-BODY */ - krtn = encode_krb5_kdc_req_body(request, &der_req); - if(krtn) { - kdcPkinitDebug("encode_krb5_kdc_req_body returned %d\n", (int)krtn); - goto cleanup; - } - krtn = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0, der_req, &cksum); - if(krtn) { - goto cleanup; - } - - krtn = krb5_us_timeofday(context, &kctime, &cusec); - if(krtn) { - goto cleanup; - } - - /* cook up a random 4-byte nonce */ - krtn = krb5_c_random_make_octets(context, &nonce_data); - if(krtn) { - goto cleanup; - } - for(dex=0; dex<4; dex++) { - nonce <<= 8; - nonce |= nonce_bytes[dex]; - } - - krtn = krb5int_pkinit_as_req_create(context, - kctime, cusec, nonce, &cksum, - client_cert, - trusted_CAs, num_trusted_CAs, - (kdc_cert.data ? &kdc_cert : NULL), - &out_data); - if(krtn) { - kdcPkinitDebug("error %d on pkinit_as_req_create; aborting PKINIT\n", (int)krtn); - goto cleanup; - } - *out_padata = (krb5_pa_data *)malloc(sizeof(krb5_pa_data)); - if(*out_padata == NULL) { - krtn = ENOMEM; - free(out_data.data); - goto cleanup; - } - (*out_padata)->magic = KV5M_PA_DATA; - (*out_padata)->pa_type = KRB5_PADATA_PK_AS_REQ; - (*out_padata)->length = out_data.length; - (*out_padata)->contents = (krb5_octet *)out_data.data; - krtn = 0; -cleanup: - if(client_cert) { - krb5_pkinit_release_cert(client_cert); - } - if(cksum.contents) { - free(cksum.contents); - } - if (der_req) { - krb5_free_data(context, der_req); - } - if(server_principal) { - free(server_principal); - } - /* free data mallocd by krb5_pkinit_get_server_certs() */ - if(trusted_CAs) { - unsigned udex; - for(udex=0; udexrealm.length <= sizeof(lkdcprefix) || - 0 != memcmp(lkdcprefix, client->realm.data, sizeof(lkdcprefix)-1)) - return match; - realm_hash = &client->realm.data[sizeof(lkdcprefix)-1]; - realm_hash_len = client->realm.length - sizeof(lkdcprefix) + 1; - kdcPkinitDebug("checking realm versus certificate hash\n"); - if (NULL != (cert_hash = krb5_pkinit_cert_hash_str(signer_cert))) { - kdcPkinitDebug("hash = %s\n", cert_hash); - cert_hash_len = strlen(cert_hash); - if (cert_hash_len == realm_hash_len && - 0 == memcmp(cert_hash, realm_hash, cert_hash_len)) - match = TRUE; - free(cert_hash); - } - kdcPkinitDebug("result: %s\n", match ? "matches" : "does not match"); - return match; -} - -static krb5_error_code -pa_pkinit_parse_rep(krb5_context context, - krb5_kdc_req *request, - krb5_pa_data *in_padata, - krb5_pa_data **out_padata, - krb5_data *salt, - krb5_data *s2kparams, - krb5_enctype *etype, - krb5_keyblock *as_key, - krb5_prompter_fct prompter, - void *prompter_data, - krb5_gic_get_as_key_fct gak_fct, - void *gak_data) -{ - krb5int_cert_sig_status sig_status = (krb5int_cert_sig_status)-999; - krb5_error_code krtn; - krb5_data asRep; - krb5_keyblock local_key = {0}; - krb5_pkinit_signing_cert_t client_cert; - char *princ_name = NULL; - krb5_checksum as_req_checksum_rcd = {0}; /* received checksum */ - krb5_checksum as_req_checksum_gen = {0}; /* calculated checksum */ - krb5_data *encoded_as_req = NULL; - krb5_data signer_cert = {0}; - - *out_padata = NULL; - kdcPkinitDebug("pa_pkinit_parse_rep\n"); - if((in_padata == NULL) || (in_padata->length== 0)) { - kdcPkinitDebug("pa_pkinit_parse_rep: no in_padata\n"); - return KRB5KDC_ERR_PREAUTH_FAILED; - } - - /* If we don't have a client cert, we're done */ - if(request->client == NULL) { - kdcPkinitDebug("No request->client; aborting PKINIT\n"); - return KRB5KDC_ERR_PREAUTH_FAILED; - } - krtn = krb5_unparse_name(context, request->client, &princ_name); - if(krtn) { - return krtn; - } - krtn = krb5_pkinit_get_client_cert(princ_name, &client_cert); - free(princ_name); - if(krtn) { - kdcPkinitDebug("No client cert; aborting PKINIT\n"); - return krtn; - } - - memset(&local_key, 0, sizeof(local_key)); - asRep.data = (char *)in_padata->contents; - asRep.length = in_padata->length; - krtn = krb5int_pkinit_as_rep_parse(context, &asRep, client_cert, - &local_key, &as_req_checksum_rcd, &sig_status, - &signer_cert, NULL, NULL); - if(krtn) { - kdcPkinitDebug("pkinit_as_rep_parse returned %d\n", (int)krtn); - return krtn; - } - switch(sig_status) { - case pki_cs_good: - break; - case pki_cs_unknown_root: - if (local_kdc_cert_match(context, &signer_cert, request->client)) - break; - /* FALLTHROUGH */ - default: - kdcPkinitDebug("pa_pkinit_parse_rep: bad cert/sig status %d\n", - (int)sig_status); - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto error_out; - } - - /* calculate checksum of incoming AS-REQ using the decryption key - * we just got from the ReplyKeyPack */ - krtn = encode_krb5_as_req(request, &encoded_as_req); - if(krtn) { - goto error_out; - } - krtn = krb5_c_make_checksum(context, context->kdc_req_sumtype, - &local_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM, - encoded_as_req, &as_req_checksum_gen); - if(krtn) { - goto error_out; - } - if((as_req_checksum_gen.length != as_req_checksum_rcd.length) || - memcmp(as_req_checksum_gen.contents, - as_req_checksum_rcd.contents, - as_req_checksum_gen.length)) { - kdcPkinitDebug("pa_pkinit_parse_rep: checksum miscompare\n"); - krtn = KRB5KDC_ERR_PREAUTH_FAILED; - goto error_out; - } - - /* We have the key; transfer to caller */ - if (as_key->length) { - krb5_free_keyblock_contents(context, as_key); - } - *as_key = local_key; - -#if PKINIT_DEBUG - fprintf(stderr, "pa_pkinit_parse_rep: SUCCESS\n"); - fprintf(stderr, "enctype %d keylen %d keydata %02x %02x %02x %02x...\n", - (int)as_key->enctype, (int)as_key->length, - as_key->contents[0], as_key->contents[1], - as_key->contents[2], as_key->contents[3]); -#endif - - krtn = 0; - -error_out: - if (signer_cert.data) { - free(signer_cert.data); - } - if(as_req_checksum_rcd.contents) { - free(as_req_checksum_rcd.contents); - } - if(as_req_checksum_gen.contents) { - free(as_req_checksum_gen.contents); - } - if(encoded_as_req) { - krb5_free_data(context, encoded_as_req); - } - if(krtn && (local_key.contents != NULL)) { - krb5_free_keyblock_contents(context, &local_key); - } - return krtn; -} -#endif /* APPLE_PKINIT */ - /* this macro expands to the int,ptr necessary for "%.*s" in an sprintf */ #define SAMDATA(kdata, str, maxsize) \ @@ -1343,18 +1025,6 @@ static const pa_types_t pa_types[] = { pa_salt, PA_INFO, }, -#if APPLE_PKINIT - { - KRB5_PADATA_PK_AS_REQ, - pa_pkinit_gen_req, - PA_INFO, - }, - { - KRB5_PADATA_PK_AS_REP, - pa_pkinit_parse_rep, - PA_REAL, - }, -#endif /* APPLE_PKINIT */ { KRB5_PADATA_SAM_CHALLENGE_2, pa_sam_2, diff --git a/src/lib/krb5/krb/str_conv.c b/src/lib/krb5/krb/str_conv.c index 21e7fd904..fd98dca57 100644 --- a/src/lib/krb5/krb/str_conv.c +++ b/src/lib/krb5/krb/str_conv.c @@ -69,9 +69,6 @@ static const struct salttype_lookup_entry salttype_table[] = { { KRB5_KDB_SALTTYPE_ONLYREALM, "onlyrealm", "Version 5 - Realm Only" }, { KRB5_KDB_SALTTYPE_SPECIAL, "special", "Special" }, { KRB5_KDB_SALTTYPE_AFS3, "afs3", "AFS version 3" }, -#if PKINIT_APPLE - { KRB5_KDB_SALTTYPE_CERTHASH, "certhash", "PKINIT Cert Hash" } -#endif /* PKINIT_APPLE */ }; static const int salttype_table_nents = sizeof(salttype_table)/ sizeof(salttype_table[0]);