From 03e756c87432e5584ddd3a739ced6ed79d5481c2 Mon Sep 17 00:00:00 2001 From: Sam Hartman Date: Mon, 19 Sep 2011 00:51:39 +0000 Subject: [PATCH] Implement encoding and decoding for supportedKDFs and kdfID pkinit: ASN.1 encoders and decoders for new KDF git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25195 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/asn.1/asn1_k_decode.c | 85 +++++++++++++++++-------- src/lib/krb5/asn.1/asn1_k_decode.h | 7 ++ src/lib/krb5/asn.1/asn1_k_decode_kdc.c | 11 +++- src/lib/krb5/asn.1/asn1_k_encode.c | 41 +++++++++--- src/plugins/preauth/pkinit/pkinit_lib.c | 4 +- 5 files changed, 111 insertions(+), 37 deletions(-) diff --git a/src/lib/krb5/asn.1/asn1_k_decode.c b/src/lib/krb5/asn.1/asn1_k_decode.c index e2ba5757f..599a2159d 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.c +++ b/src/lib/krb5/asn.1/asn1_k_decode.c @@ -447,31 +447,6 @@ error_out: retval = decoder(&seqbuf,&element); \ if (retval) clean_return(retval) -static void * -array_expand (void *array, int n_elts, size_t elt_size) -{ - size_t new_size; - - if (n_elts <= 0) - return NULL; - if ((unsigned int) n_elts > SIZE_MAX / elt_size) - return NULL; - new_size = n_elts * elt_size; - if (new_size == 0) - return NULL; - if (new_size / elt_size != (unsigned int) n_elts) - return NULL; - return realloc(array, new_size); -} - -#define array_append(array,size,element,type) \ - { \ - void *new_array = array_expand(*(array), (size)+2, sizeof(type*)); \ - if (new_array == NULL) clean_return(ENOMEM); \ - *(array) = new_array; \ - (*(array))[(size)++] = elt; \ - } - /* * Function body for array decoders. freefn is expected to look like * a krb5_free_ function, so we pass a null first argument. @@ -503,6 +478,32 @@ for (i = 0; i < size; i++) \ free(array); \ return retval +static void * +array_expand (void *array, int n_elts, size_t elt_size) +{ + size_t new_size; + + if (n_elts <= 0) + return NULL; + if ((unsigned int) n_elts > SIZE_MAX / elt_size) + return NULL; + new_size = n_elts * elt_size; + if (new_size == 0) + return NULL; + if (new_size / elt_size != (unsigned int) n_elts) + return NULL; + return realloc(array, new_size); +} + +#define array_append(array,size,element,type) \ + { \ + void *new_array = array_expand(*(array), (size)+2, sizeof(type*)); \ + if (new_array == NULL) clean_return(ENOMEM); \ + *(array) = new_array; \ + (*(array))[(size)++] = elt; \ + } + + static void free_authdata_elt(void *dummy, krb5_authdata *val) { @@ -1347,22 +1348,33 @@ asn1_decode_sequence_of_trusted_ca(asn1buf *buf, krb5_trusted_ca ***val) free_trusted_ca); } +static asn1_error_code +asn1_decode_kdf_alg_id_ptr( asn1buf *buf, + krb5_octet_data **valptr) +{ + decode_ptr(krb5_octet_data *, asn1_decode_kdf_alg_id); +} + asn1_error_code asn1_decode_dh_rep_info(asn1buf *buf, krb5_dh_rep_info *val) { setup(); val->dhSignedData.data = NULL; val->serverDHNonce.data = NULL; + val->kdfID = NULL; { begin_structure(); get_implicit_octet_string(val->dhSignedData.length, val->dhSignedData.data, 0); opt_lenfield(val->serverDHNonce.length, val->serverDHNonce.data, 1, asn1_decode_octetstring); + opt_field(val->kdfID, 2, asn1_decode_kdf_alg_id_ptr, NULL); end_structure(); } return 0; error_out: free(val->dhSignedData.data); free(val->serverDHNonce.data); + krb5_free_octet_data(NULL, val->kdfID); + val->kdfID = NULL; val->dhSignedData.data = NULL; val->serverDHNonce.data = NULL; return retval; @@ -1717,3 +1729,26 @@ asn1_decode_typed_data_ptr(asn1buf *buf, krb5_typed_data **valptr) { decode_ptr(krb5_typed_data *, asn1_decode_typed_data); } + +asn1_error_code +asn1_decode_kdf_alg_id( asn1buf *buf, krb5_octet_data *val) +{ + setup(); + val->data = NULL; + { begin_structure(); + get_lenfield(val->length,val->data,0,asn1_decode_oid); + end_structure(); + } + return 0; +error_out: + free(val->data); + return retval; +} + + asn1_error_code +asn1_decode_sequence_of_kdf_alg_id(asn1buf *buf, + krb5_octet_data ***val) +{ + decode_array_body(krb5_octet_data, asn1_decode_kdf_alg_id_ptr, + krb5_free_octet_data); +} diff --git a/src/lib/krb5/asn.1/asn1_k_decode.h b/src/lib/krb5/asn.1/asn1_k_decode.h index 8f7bf0ccd..ed51ab164 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode.h +++ b/src/lib/krb5/asn.1/asn1_k_decode.h @@ -276,4 +276,11 @@ asn1_error_code asn1_decode_iakerb_header(asn1buf *buf, asn1_error_code asn1_decode_iakerb_finished(asn1buf *buf, krb5_iakerb_finished *val); +asn1_error_code +asn1_decode_kdf_alg_id( asn1buf *buf, krb5_octet_data *val); + + asn1_error_code +asn1_decode_sequence_of_kdf_alg_id(asn1buf *buf, + krb5_octet_data ***val); + #endif diff --git a/src/lib/krb5/asn.1/asn1_k_decode_kdc.c b/src/lib/krb5/asn.1/asn1_k_decode_kdc.c index 1711ca04a..c0aa2a2c3 100644 --- a/src/lib/krb5/asn.1/asn1_k_decode_kdc.c +++ b/src/lib/krb5/asn.1/asn1_k_decode_kdc.c @@ -207,6 +207,7 @@ asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val) val->pkAuthenticator.paChecksum.contents = NULL; val->supportedCMSTypes = NULL; val->clientDHNonce.data = NULL; + val->supportedKDFs = NULL; { begin_structure(); get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator); if (tagnum == 1) { @@ -238,7 +239,8 @@ asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val) } else val->supportedCMSTypes = NULL; } opt_lenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_decode_octetstring); - end_structure(); + opt_field(val->supportedKDFs, 4, asn1_decode_sequence_of_kdf_alg_id, NULL); + end_structure(); } return 0; error_out: @@ -255,6 +257,13 @@ error_out: free(val->supportedCMSTypes); } free(val->clientDHNonce.data); + if (val->supportedKDFs) { + + for (i=0; val->supportedKDFs[i]; i++) + krb5_free_octet_data(NULL, val->supportedKDFs[i]); + free(val->supportedKDFs); + val->supportedKDFs = NULL; + } val->clientPublicValue = NULL; val->pkAuthenticator.paChecksum.contents = NULL; val->supportedCMSTypes = NULL; diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index 7bca6d23b..9d06de109 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -1422,10 +1422,27 @@ DEFSEQTYPE(iakerb_finished, krb5_iakerb_finished, iakerb_finished_fields, iakerb_finished_optional); DEFFNXTYPE(algorithm_identifier, krb5_algorithm_identifier, asn1_encode_algorithm_identifier); +DEFFNLENTYPE(object_identifier, asn1_octet *, asn1_encode_oid); +DEFFIELDTYPE(oid_data, krb5_octet_data, + FIELDOF_STRING(krb5_octet_data,object_identifier, data, length, -1)); +DEFPTRTYPE(oid_data_ptr, oid_data); + +static const struct field_info kdf_alg_id_fields[] = { + FIELDOF_ENCODEAS(krb5_octet_data, oid_data, 0) +}; +DEFSEQTYPE(kdf_alg_id, krb5_octet_data, kdf_alg_id_fields, NULL); +DEFPTRTYPE(kdf_alg_id_ptr, kdf_alg_id); +DEFNONEMPTYNULLTERMSEQOFTYPE(supported_kdfs, kdf_alg_id_ptr); +DEFPTRTYPE(supported_kdfs_ptr, supported_kdfs); +MAKE_ENCFN(asn1_encode_supported_kdfs, + supported_kdfs); +MAKE_ENCFN(asn1_encode_kdf_alg_id, kdf_alg_id); + + /* Krb5PrincipalName is defined in RFC 4556 and is *not* PrincipalName from RFC 4120*/ static const struct field_info pkinit_krb5_principal_name_fields[] = { - FIELDOF_NORM(krb5_principal_data, gstring_data, realm, 0), - FIELDOF_ENCODEAS(krb5_principal_data, principal_data, 1) + FIELDOF_NORM(krb5_principal_data, gstring_data, realm, 0), + FIELDOF_ENCODEAS(krb5_principal_data, principal_data, 1) }; @@ -1436,20 +1453,20 @@ DEFOCTETWRAPTYPE(pkinit_krb5_principal_name_wrapped, pkinit_krb5_principal_name) /* For SP80056A OtherInfo, for pkinit agility */ static const struct field_info sp80056a_other_info_fields[] = { - FIELDOF_NORM(krb5_sp80056a_other_info, algorithm_identifier, algorithm_identifier, -1), - FIELDOF_NORM(krb5_sp80056a_other_info, pkinit_krb5_principal_name_wrapped, party_u_info, 0), - FIELDOF_NORM(krb5_sp80056a_other_info, pkinit_krb5_principal_name_wrapped, party_v_info, 1), - FIELDOF_STRING(krb5_sp80056a_other_info, s_octetstring, supp_pub_info.data, supp_pub_info.length, 2), + FIELDOF_NORM(krb5_sp80056a_other_info, algorithm_identifier, algorithm_identifier, -1), + FIELDOF_NORM(krb5_sp80056a_other_info, pkinit_krb5_principal_name_wrapped, party_u_info, 0), + FIELDOF_NORM(krb5_sp80056a_other_info, pkinit_krb5_principal_name_wrapped, party_v_info, 1), + FIELDOF_STRING(krb5_sp80056a_other_info, s_octetstring, supp_pub_info.data, supp_pub_info.length, 2), }; DEFSEQTYPE(sp80056a_other_info, krb5_sp80056a_other_info, sp80056a_other_info_fields, NULL); /* For PkinitSuppPubInfo, for pkinit agility */ static const struct field_info pkinit_supp_pub_info_fields[] = { - FIELDOF_NORM(krb5_pkinit_supp_pub_info, int32, enctype, 0), - FIELDOF_STRING(krb5_pkinit_supp_pub_info, octetstring, as_req.data, as_req.length, 1), - FIELDOF_STRING(krb5_pkinit_supp_pub_info, octetstring, pk_as_rep.data, pk_as_rep.length, 2), - FIELDOF_NORM(krb5_pkinit_supp_pub_info, ticket_ptr, ticket, 3), + FIELDOF_NORM(krb5_pkinit_supp_pub_info, int32, enctype, 0), + FIELDOF_STRING(krb5_pkinit_supp_pub_info, octetstring, as_req.data, as_req.length, 1), + FIELDOF_STRING(krb5_pkinit_supp_pub_info, octetstring, pk_as_rep.data, pk_as_rep.length, 2), + FIELDOF_NORM(krb5_pkinit_supp_pub_info, ticket_ptr, ticket, 3), }; DEFSEQTYPE(pkinit_supp_pub_info, krb5_pkinit_supp_pub_info, pkinit_supp_pub_info_fields, NULL); @@ -1803,6 +1820,8 @@ asn1_encode_auth_pack(asn1buf *buf, const krb5_auth_pack *val, { asn1_setup(); + if (val->supportedKDFs != NULL) + asn1_addfield( val->supportedKDFs, 4, asn1_encode_supported_kdfs); if (val->clientDHNonce.length != 0) asn1_addlenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_encode_octetstring); if (val->supportedCMSTypes != NULL) @@ -1965,6 +1984,8 @@ asn1_encode_dh_rep_info(asn1buf *buf, const krb5_dh_rep_info *val, { asn1_setup(); + if (val->kdfID) + asn1_addfield(val->kdfID, 2, asn1_encode_kdf_alg_id); if (val->serverDHNonce.length != 0) asn1_insert_implicit_octetstring(val->serverDHNonce.length,val->serverDHNonce.data,1); diff --git a/src/plugins/preauth/pkinit/pkinit_lib.c b/src/plugins/preauth/pkinit/pkinit_lib.c index 8eb64019c..034587b13 100644 --- a/src/plugins/preauth/pkinit/pkinit_lib.c +++ b/src/plugins/preauth/pkinit/pkinit_lib.c @@ -163,7 +163,7 @@ free_krb5_auth_pack(krb5_auth_pack **in) free((*in)->pkAuthenticator.paChecksum.contents); if ((*in)->supportedCMSTypes != NULL) free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes)); - if (*(*in)->supportedKDFs) { + if ((*in)->supportedKDFs) { krb5_octet_data **supportedKDFs = (*in)->supportedKDFs; unsigned i; @@ -356,6 +356,7 @@ init_krb5_auth_pack(krb5_auth_pack **in) (*in)->clientDHNonce.length = 0; (*in)->clientDHNonce.data = NULL; (*in)->pkAuthenticator.paChecksum.contents = NULL; + (*in)->supportedKDFs = NULL; } void @@ -377,6 +378,7 @@ init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in) (*in)->u.dh_Info.dhSignedData.data = NULL; (*in)->u.encKeyPack.length = 0; (*in)->u.encKeyPack.data = NULL; + (*in)->u.dh_Info.kdfID = NULL; } void -- 2.26.2