From c3751ec386c0367b9c5024b2b91cdc5d11f6b8f8 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Fri, 13 Jan 2012 15:04:35 +0000 Subject: [PATCH] Add PKINIT decoder tests Add tests to krb5_decode_test.c for PKINIT types. Where the decoders do not match the encoders, include comments and hand-generated encodings which work with the decoder. Add a comment to asn1_k_encode.c documenting inconsistencies between the draft 9 PA-PK-AS-REQ spec and our encoder results. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25650 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/asn.1/asn1_k_encode.c | 9 ++ src/tests/asn.1/krb5_decode_test.c | 214 +++++++++++++++++++++++++ src/tests/asn.1/ktest.c | 2 + src/tests/asn.1/ktest_equal.c | 246 +++++++++++++++++++++++++++++ src/tests/asn.1/ktest_equal.h | 13 ++ 5 files changed, 484 insertions(+) diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c index 20a597926..f9af88d75 100644 --- a/src/lib/krb5/asn.1/asn1_k_encode.c +++ b/src/lib/krb5/asn.1/asn1_k_encode.c @@ -1632,6 +1632,15 @@ DEFFIELDTYPE(pa_pk_as_rep, krb5_pa_pk_as_rep, FIELDOF_CHOICE(krb5_pa_pk_as_rep, pa_pk_as_rep_choice, u, choice, pa_pk_as_rep_selection, -1)); +/* + * draft-ietf-cat-kerberos-pk-init-09 specifies these alternatives as + * explicitly tagged SignedData and EnvelopedData respectively, which means + * they should have constructed context tags. However, our historical behavior + * is to use primitive context tags, and we don't want to change that behavior + * without interop testing. We have the encodings for each alternative in a + * krb5_data object; pretend that they are wrapped in IMPLICIT OCTET STRING in + * order to wrap them in primitive [0] and [1] tags. + */ typedef union krb5_pa_pk_as_rep_draft9_choices krb5_pa_pk_as_rep_draft9_choices; typedef enum krb5_pa_pk_as_rep_draft9_selection diff --git a/src/tests/asn.1/krb5_decode_test.c b/src/tests/asn.1/krb5_decode_test.c index 873927a6f..c85c77a8c 100644 --- a/src/tests/asn.1/krb5_decode_test.c +++ b/src/tests/asn.1/krb5_decode_test.c @@ -38,6 +38,25 @@ int error_count = 0; void krb5_ktest_free_enc_data(krb5_context context, krb5_enc_data *val); +#ifndef DISABLE_PKINIT +static int equal_principal(krb5_principal *ref, krb5_principal var); +static void ktest_free_auth_pack(krb5_context context, krb5_auth_pack *val); +static void ktest_free_auth_pack_draft9(krb5_context context, + krb5_auth_pack_draft9 *val); +static void ktest_free_kdc_dh_key_info(krb5_context context, + krb5_kdc_dh_key_info *val); +static void ktest_free_pa_pk_as_req(krb5_context context, + krb5_pa_pk_as_req *val); +static void ktest_free_pa_pk_as_rep(krb5_context context, + krb5_pa_pk_as_rep *val); +static void ktest_free_pa_pk_as_rep_draft9(krb5_context context, + krb5_pa_pk_as_rep_draft9 *val); +static void ktest_free_reply_key_pack(krb5_context context, + krb5_reply_key_pack *val); +static void ktest_free_reply_key_pack_draft9(krb5_context context, + krb5_reply_key_pack_draft9 *val); +#endif + int main(argc, argv) int argc; char **argv; @@ -929,6 +948,123 @@ int main(argc, argv) ktest_destroy_enc_data(&ref); } +#ifndef DISABLE_PKINIT + + /****************************************************************/ + /* decode_krb5_pa_pk_as_req */ + { + setup(krb5_pa_pk_as_req,ktest_make_sample_pa_pk_as_req); + decode_run("krb5_pa_pk_as_req","","30 38 80 08 6B 72 62 35 64 61 74 61 A1 22 30 20 30 1E 80 08 6B 72 62 35 64 61 74 61 81 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61 82 08 6B 72 62 35 64 61 74 61", + acc.decode_krb5_pa_pk_as_req, + ktest_equal_pa_pk_as_req,ktest_free_pa_pk_as_req); + ktest_empty_pa_pk_as_req(&ref); + } + + /****************************************************************/ + /* decode_krb5_pa_pk_as_rep */ + { + setup(krb5_pa_pk_as_rep,ktest_make_sample_pa_pk_as_rep_dhInfo); + decode_run("krb5_pa_pk_as_rep","(dhInfo)","A0 28 30 26 80 08 6B 72 62 35 64 61 74 61 A1 0A 04 08 6B 72 62 35 64 61 74 61 A2 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61", + acc.decode_krb5_pa_pk_as_rep, + ktest_equal_pa_pk_as_rep,ktest_free_pa_pk_as_rep); + ktest_empty_pa_pk_as_rep(&ref); + } + { + setup(krb5_pa_pk_as_rep,ktest_make_sample_pa_pk_as_rep_encKeyPack); + decode_run("krb5_pa_pk_as_rep","(encKeyPack)","81 08 6B 72 62 35 64 61 74 61", + acc.decode_krb5_pa_pk_as_rep, + ktest_equal_pa_pk_as_rep,ktest_free_pa_pk_as_rep); + ktest_empty_pa_pk_as_rep(&ref); + } + + /****************************************************************/ + /* decode_krb5_pa_pk_as_rep_draft9 */ + /* + * NOTE: These are NOT the encodings produced by + * encode_krb5_pa_pk_as_rep_draft9; they are hand-generated to match what + * the decoder expects. The decoder expects a sequence containing an + * explicitly tagged octet string, while the encoder produces an implicitly + * tagged octet string. See issue #7072. + */ + { + setup(krb5_pa_pk_as_rep_draft9,ktest_make_sample_pa_pk_as_rep_draft9_dhSignedData); + decode_run("krb5_pa_pk_as_rep_draft9","(dhSignedData)","30 0C A0 0A 04 08 6B 72 62 35 64 61 74 61", + acc.decode_krb5_pa_pk_as_rep_draft9, + ktest_equal_pa_pk_as_rep_draft9,ktest_free_pa_pk_as_rep_draft9); + ktest_empty_pa_pk_as_rep_draft9(&ref); + } + { + setup(krb5_pa_pk_as_rep_draft9,ktest_make_sample_pa_pk_as_rep_draft9_encKeyPack); + decode_run("krb5_pa_pk_as_rep_draft9","(encKeyPack)","30 0C A1 0A 04 08 6B 72 62 35 64 61 74 61", + acc.decode_krb5_pa_pk_as_rep_draft9, + ktest_equal_pa_pk_as_rep_draft9,ktest_free_pa_pk_as_rep_draft9); + ktest_empty_pa_pk_as_rep_draft9(&ref); + } + + /****************************************************************/ + /* decode_krb5_auth_pack */ + { + setup(krb5_auth_pack,ktest_make_sample_auth_pack); + decode_run("krb5_auth_pack","","30 81 93 A0 29 30 27 A0 05 02 03 01 E2 40 A1 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A2 03 02 01 2A A3 06 04 04 31 32 33 34 A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61 A2 24 30 22 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 30 0B 06 09 2A 86 48 86 F7 12 01 02 02 A3 0A 04 08 6B 72 62 35 64 61 74 61 A4 10 30 0E 30 0C A0 0A 06 08 6B 72 62 35 64 61 74 61", + acc.decode_krb5_auth_pack, + ktest_equal_auth_pack,ktest_free_auth_pack); + ktest_empty_auth_pack(&ref); + } + + /****************************************************************/ + /* decode_krb5_auth_pack_draft9 */ + { + setup(krb5_auth_pack_draft9,ktest_make_sample_auth_pack_draft9); + decode_run("krb5_auth_pack_draft9","","30 75 A0 4F 30 4D A0 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 05 02 03 01 E2 40 A3 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A4 03 02 01 2A A1 22 30 20 30 13 06 09 2A 86 48 86 F7 12 01 02 02 04 06 70 61 72 61 6D 73 03 09 00 6B 72 62 35 64 61 74 61", + acc.decode_krb5_auth_pack_draft9, + ktest_equal_auth_pack_draft9,ktest_free_auth_pack_draft9); + ktest_empty_auth_pack_draft9(&ref); + } + + /****************************************************************/ + /* decode_krb5_kdc_dh_key_info */ + { + setup(krb5_kdc_dh_key_info,ktest_make_sample_kdc_dh_key_info); + decode_run("krb5_kdc_dh_key_info","","30 25 A0 0B 03 09 00 6B 72 62 35 64 61 74 61 A1 03 02 01 2A A2 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A", + acc.decode_krb5_kdc_dh_key_info, + ktest_equal_kdc_dh_key_info,ktest_free_kdc_dh_key_info); + ktest_empty_kdc_dh_key_info(&ref); + } + + /****************************************************************/ + /* decode_krb5_reply_key_pack */ + { + setup(krb5_reply_key_pack,ktest_make_sample_reply_key_pack); + decode_run("krb5_reply_key_pack","","30 26 A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 0F 30 0D A0 03 02 01 01 A1 06 04 04 31 32 33 34", + acc.decode_krb5_reply_key_pack, + ktest_equal_reply_key_pack,ktest_free_reply_key_pack); + ktest_empty_reply_key_pack(&ref); + } + + /****************************************************************/ + /* decode_krb5_reply_key_pack_draft9 */ + { + setup(krb5_reply_key_pack_draft9,ktest_make_sample_reply_key_pack_draft9); + decode_run("krb5_reply_key_pack_draft9","","30 1A A0 13 30 11 A0 03 02 01 01 A1 0A 04 08 31 32 33 34 35 36 37 38 A1 03 02 01 2A", + acc.decode_krb5_reply_key_pack_draft9, + ktest_equal_reply_key_pack_draft9,ktest_free_reply_key_pack_draft9); + ktest_empty_reply_key_pack_draft9(&ref); + } + + /****************************************************************/ + /* decode_krb5_principal_name */ + /* We have no encoder for this type (KerberosName from RFC 4556); the + * encoding is hand-generated. */ + { + krb5_principal ref, var; + + ktest_make_sample_principal(&ref); + decode_run("krb5_principal_name","","30 2E A0 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A1 1A 30 18 A0 03 02 01 01 A1 11 30 0F 1B 06 68 66 74 73 61 69 1B 05 65 78 74 72 61", + acc.decode_krb5_principal_name,equal_principal,krb5_free_principal); + } + +#endif /* not DISABLE_PKINIT */ + #ifdef ENABLE_LDAP /* ldap sequence_of_keys */ { @@ -952,3 +1088,81 @@ void krb5_ktest_free_enc_data(krb5_context context, krb5_enc_data *val) free(val); } } + +#ifndef DISABLE_PKINIT + +/* Glue function to make ktest_equal_principal_data look like what decode_run + * expects. */ +static int +equal_principal(krb5_principal *ref, krb5_principal var) +{ + return ktest_equal_principal_data(*ref, var); +} + +static void +ktest_free_auth_pack(krb5_context context, krb5_auth_pack *val) +{ + if (val) + ktest_empty_auth_pack(val); + free(val); +} + +static void +ktest_free_auth_pack_draft9(krb5_context context, krb5_auth_pack_draft9 *val) +{ + if (val) + ktest_empty_auth_pack_draft9(val); + free(val); +} + +static void +ktest_free_kdc_dh_key_info(krb5_context context, krb5_kdc_dh_key_info *val) +{ + if (val) + ktest_empty_kdc_dh_key_info(val); + free(val); +} + +static void +ktest_free_pa_pk_as_req(krb5_context context, krb5_pa_pk_as_req *val) +{ + if (val) + ktest_empty_pa_pk_as_req(val); + free(val); +} + +static void +ktest_free_pa_pk_as_rep(krb5_context context, krb5_pa_pk_as_rep *val) +{ + if (val) + ktest_empty_pa_pk_as_rep(val); + free(val); +} + +static void +ktest_free_pa_pk_as_rep_draft9(krb5_context context, + krb5_pa_pk_as_rep_draft9 *val) +{ + if (val) + ktest_empty_pa_pk_as_rep_draft9(val); + free(val); +} + +static void +ktest_free_reply_key_pack(krb5_context context, krb5_reply_key_pack *val) +{ + if (val) + ktest_empty_reply_key_pack(val); + free(val); +} + +static void +ktest_free_reply_key_pack_draft9(krb5_context context, + krb5_reply_key_pack_draft9 *val) +{ + if (val) + ktest_empty_reply_key_pack_draft9(val); + free(val); +} + +#endif /* not DISABLE_PKINIT */ diff --git a/src/tests/asn.1/ktest.c b/src/tests/asn.1/ktest.c index 4af530d90..330756453 100644 --- a/src/tests/asn.1/ktest.c +++ b/src/tests/asn.1/ktest.c @@ -624,6 +624,8 @@ ktest_make_sample_pk_authenticator(krb5_pk_authenticator *p) p->ctime = SAMPLE_TIME; p->nonce = SAMPLE_NONCE; ktest_make_sample_checksum(&p->paChecksum); + /* We don't encode the checksum type, only the contents. */ + p->paChecksum.checksum_type = 0; } static void diff --git a/src/tests/asn.1/ktest_equal.c b/src/tests/asn.1/ktest_equal.c index 53924ff5a..ea218c930 100644 --- a/src/tests/asn.1/ktest_equal.c +++ b/src/tests/asn.1/ktest_equal.c @@ -770,3 +770,249 @@ ktest_equal_sequence_of_checksum(krb5_checksum **ref, krb5_checksum **var) { array_compare(ktest_equal_checksum); } + +#ifndef DISABLE_PKINIT + +static int +ktest_equal_pk_authenticator(krb5_pk_authenticator *ref, + krb5_pk_authenticator *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && scalar_equal(cusec); + p = p && scalar_equal(ctime); + p = p && scalar_equal(nonce); + p = p && struct_equal(paChecksum, ktest_equal_checksum); + return p; +} + +static int +ktest_equal_pk_authenticator_draft9(krb5_pk_authenticator_draft9 *ref, + krb5_pk_authenticator_draft9 *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && ptr_equal(kdcName, ktest_equal_principal_data); + p = p && scalar_equal(cusec); + p = p && scalar_equal(ctime); + p = p && scalar_equal(nonce); + return p; +} + +static int +ktest_equal_algorithm_identifier(krb5_algorithm_identifier *ref, + krb5_algorithm_identifier *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && equal_str(algorithm); + p = p && equal_str(parameters); + return p; +} + +static int +ktest_equal_sequence_of_algorithm_identifier(krb5_algorithm_identifier **ref, + krb5_algorithm_identifier **var) +{ + array_compare(ktest_equal_algorithm_identifier); +} + +static int +ktest_equal_subject_pk_info(krb5_subject_pk_info *ref, + krb5_subject_pk_info *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(algorithm, ktest_equal_algorithm_identifier); + p = p && equal_str(subjectPublicKey); + return p; +} + +static int +ktest_equal_external_principal_identifier( + krb5_external_principal_identifier *ref, + krb5_external_principal_identifier *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && equal_str(subjectName); + p = p && equal_str(issuerAndSerialNumber); + p = p && equal_str(subjectKeyIdentifier); + return p; +} + +static int +ktest_equal_sequence_of_external_principal_identifier( + krb5_external_principal_identifier **ref, + krb5_external_principal_identifier **var) +{ + array_compare(ktest_equal_external_principal_identifier); +} + +static int +ktest_equal_trusted_ca(krb5_trusted_ca *ref, krb5_trusted_ca *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + if (ref->choice != var->choice) return FALSE; + if (ref->choice == choice_trusted_cas_principalName) + p = p && ptr_equal(u.principalName, ktest_equal_principal_data); + else if (ref->choice == choice_trusted_cas_caName) + p = p && equal_str(u.caName); + else if (ref->choice == choice_trusted_cas_issuerAndSerial) + p = p && equal_str(u.issuerAndSerial); + return p; +} + +static int +ktest_equal_sequence_of_trusted_ca(krb5_trusted_ca **ref, + krb5_trusted_ca **var) +{ + array_compare(ktest_equal_trusted_ca); +} + +int +ktest_equal_pa_pk_as_req(krb5_pa_pk_as_req *ref, krb5_pa_pk_as_req *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && equal_str(signedAuthPack); + p = p && ptr_equal(trustedCertifiers, + ktest_equal_sequence_of_external_principal_identifier); + p = p && equal_str(kdcPkId); + return p; +} + +int +ktest_equal_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 *ref, + krb5_pa_pk_as_req_draft9 *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && equal_str(signedAuthPack); + p = p && ptr_equal(trustedCertifiers, ktest_equal_sequence_of_trusted_ca); + p = p && equal_str(kdcCert); + p = p && equal_str(encryptionCert); + return p; +} + +static int +ktest_equal_dh_rep_info(krb5_dh_rep_info *ref, krb5_dh_rep_info *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && equal_str(dhSignedData); + p = p && equal_str(serverDHNonce); + p = p && ptr_equal(kdfID, ktest_equal_data); + return p; +} + +int +ktest_equal_pa_pk_as_rep(krb5_pa_pk_as_rep *ref, krb5_pa_pk_as_rep *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + if (ref->choice != var->choice) return FALSE; + if (ref->choice == choice_pa_pk_as_rep_dhInfo) + p = p && struct_equal(u.dh_Info, ktest_equal_dh_rep_info); + else if (ref->choice == choice_pa_pk_as_rep_encKeyPack) + p = p && equal_str(u.encKeyPack); + return p; +} + +int +ktest_equal_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 *ref, + krb5_pa_pk_as_rep_draft9 *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + if (ref->choice != var->choice) return FALSE; + if (ref->choice == choice_pa_pk_as_rep_draft9_dhSignedData) + p = p && equal_str(u.dhSignedData); + else if (ref->choice == choice_pa_pk_as_rep_draft9_encKeyPack) + p = p && equal_str(u.encKeyPack); + return p; +} + +static int +ktest_equal_sequence_of_data(krb5_data **ref, krb5_data **var) +{ + array_compare(ktest_equal_data); +} + +int +ktest_equal_auth_pack(krb5_auth_pack *ref, krb5_auth_pack *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(pkAuthenticator, ktest_equal_pk_authenticator); + p = p && ptr_equal(clientPublicValue, ktest_equal_subject_pk_info); + p = p && ptr_equal(supportedCMSTypes, + ktest_equal_sequence_of_algorithm_identifier); + p = p && equal_str(clientDHNonce); + p = p && ptr_equal(supportedKDFs, ktest_equal_sequence_of_data); + return p; +} + +int +ktest_equal_auth_pack_draft9(krb5_auth_pack_draft9 *ref, + krb5_auth_pack_draft9 *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(pkAuthenticator, + ktest_equal_pk_authenticator_draft9); + p = p && ptr_equal(clientPublicValue, ktest_equal_subject_pk_info); + return p; +} + +int +ktest_equal_kdc_dh_key_info(krb5_kdc_dh_key_info *ref, + krb5_kdc_dh_key_info *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && equal_str(subjectPublicKey); + p = p && scalar_equal(nonce); + p = p && scalar_equal(dhKeyExpiration); + return p; +} + +int +ktest_equal_reply_key_pack(krb5_reply_key_pack *ref, krb5_reply_key_pack *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(replyKey, ktest_equal_keyblock); + p = p && struct_equal(asChecksum, ktest_equal_checksum); + return p; +} + +int +ktest_equal_reply_key_pack_draft9(krb5_reply_key_pack_draft9 *ref, + krb5_reply_key_pack_draft9 *var) +{ + int p = TRUE; + if (ref == var) return TRUE; + else if (ref == NULL || var == NULL) return FALSE; + p = p && struct_equal(replyKey, ktest_equal_keyblock); + p = p && scalar_equal(nonce); + return p; +} + +#endif /* not DISABLE_PKINIT */ diff --git a/src/tests/asn.1/ktest_equal.h b/src/tests/asn.1/ktest_equal.h index 2a2b6f04d..9e88a8ccd 100644 --- a/src/tests/asn.1/ktest_equal.h +++ b/src/tests/asn.1/ktest_equal.h @@ -123,4 +123,17 @@ int ktest_equal_fast_response(krb5_fast_response *ref, int ktest_equal_ldap_sequence_of_keys(ldap_seqof_key_data *ref, ldap_seqof_key_data *var); + +#ifndef DISABLE_PKINIT +generic(ktest_equal_pa_pk_as_req, krb5_pa_pk_as_req); +generic(ktest_equal_pa_pk_as_req_draft9, krb5_pa_pk_as_req_draft9); +generic(ktest_equal_pa_pk_as_rep, krb5_pa_pk_as_rep); +generic(ktest_equal_pa_pk_as_rep_draft9, krb5_pa_pk_as_rep_draft9); +generic(ktest_equal_auth_pack, krb5_auth_pack); +generic(ktest_equal_auth_pack_draft9, krb5_auth_pack_draft9); +generic(ktest_equal_kdc_dh_key_info, krb5_kdc_dh_key_info); +generic(ktest_equal_reply_key_pack, krb5_reply_key_pack); +generic(ktest_equal_reply_key_pack_draft9, krb5_reply_key_pack_draft9); +#endif /* not DISABLE_PKINIT */ + #endif -- 2.26.2