Skip to content

Commit

Permalink
Add ASN.1 encoder and decoder for CAMMAC
Browse files Browse the repository at this point in the history
Add internal type declarations for krb5_verifier_mac and krb5_cammac.
Add ASN.1 encoder and decoder functions and an internal free function
for krb5_cammac.  Add ASN.1 tests for krb5_cammac as well as asn1c
test vectors for Verifier and AD-CAMMAC.
  • Loading branch information
greghudson committed Jul 10, 2015
1 parent 2c3c44c commit 6a06997
Show file tree
Hide file tree
Showing 15 changed files with 382 additions and 6 deletions.
27 changes: 27 additions & 0 deletions src/include/k5-int.h
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,26 @@ typedef struct _krb5_iakerb_finished {
krb5_checksum checksum;
} krb5_iakerb_finished;

typedef struct _krb5_verifier_mac {
krb5_principal princ;
krb5_kvno kvno;
krb5_enctype enctype;
krb5_checksum checksum;
} krb5_verifier_mac;

/*
* AD-CAMMAC's other-verifiers field is a sequence of Verifier, which is an
* extensible choice with only one selection, Verifier-MAC. For the time being
* we will represent this field directly as an array of krb5_verifier_mac.
* That will have to change if other selections are added.
*/
typedef struct _krb5_cammac {
krb5_authdata **elements;
krb5_verifier_mac *kdc_verifier;
krb5_verifier_mac *svc_verifier;
krb5_verifier_mac **other_verifiers;
} krb5_cammac;

krb5_pa_data *
krb5int_find_pa_data(krb5_context, krb5_pa_data *const *, krb5_preauthtype);
/* Does not return a copy; original padata sequence responsible for freeing*/
Expand Down Expand Up @@ -920,6 +940,7 @@ void k5_free_pa_otp_challenge(krb5_context context,
krb5_pa_otp_challenge *val);
void k5_free_pa_otp_req(krb5_context context, krb5_pa_otp_req *val);
void k5_free_kkdcp_message(krb5_context context, krb5_kkdcp_message *val);
void k5_free_cammac(krb5_context context, krb5_cammac *val);

/* #include "krb5/wordsize.h" -- comes in through base-defs.h. */
#include "com_err.h"
Expand Down Expand Up @@ -1470,6 +1491,9 @@ encode_krb5_pa_otp_enc_req(const krb5_data *, krb5_data **);
krb5_error_code
encode_krb5_kkdcp_message(const krb5_kkdcp_message *, krb5_data **);

krb5_error_code
encode_krb5_cammac(const krb5_cammac *, krb5_data **);

/*************************************************************************
* End of prototypes for krb5_encode.c
*************************************************************************/
Expand Down Expand Up @@ -1643,6 +1667,9 @@ decode_krb5_pa_otp_enc_req(const krb5_data *, krb5_data **);
krb5_error_code
decode_krb5_kkdcp_message(const krb5_data *, krb5_kkdcp_message **);

krb5_error_code
decode_krb5_cammac(const krb5_data *, krb5_cammac **);

struct _krb5_key_data; /* kdb.h */

struct ldap_seqof_key_data {
Expand Down
27 changes: 27 additions & 0 deletions src/lib/krb5/asn.1/asn1_k_encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1766,3 +1766,30 @@ DEFSEQTYPE(kkdcp_message, krb5_kkdcp_message,
kkdcp_message_fields);
MAKE_ENCODER(encode_krb5_kkdcp_message, kkdcp_message);
MAKE_DECODER(decode_krb5_kkdcp_message, kkdcp_message);

DEFFIELD(vmac_0, krb5_verifier_mac, princ, 0, opt_principal);
DEFFIELD(vmac_1, krb5_verifier_mac, kvno, 1, opt_kvno);
DEFFIELD(vmac_2, krb5_verifier_mac, enctype, 2, opt_int32);
DEFFIELD(vmac_3, krb5_verifier_mac, checksum, 3, checksum);
static const struct atype_info *vmac_fields[] = {
&k5_atype_vmac_0, &k5_atype_vmac_1, &k5_atype_vmac_2, &k5_atype_vmac_3
};
DEFSEQTYPE(vmac, krb5_verifier_mac, vmac_fields);
DEFPTRTYPE(vmac_ptr, vmac);
DEFOPTIONALZEROTYPE(opt_vmac_ptr, vmac_ptr);
DEFNONEMPTYNULLTERMSEQOFTYPE(vmacs, vmac_ptr);
DEFPTRTYPE(vmacs_ptr, vmacs);
DEFOPTIONALEMPTYTYPE(opt_vmacs_ptr, vmacs_ptr);

DEFFIELD(cammac_0, krb5_cammac, elements, 0, auth_data_ptr);
DEFFIELD(cammac_1, krb5_cammac, kdc_verifier, 1, opt_vmac_ptr);
DEFFIELD(cammac_2, krb5_cammac, svc_verifier, 2, opt_vmac_ptr);
DEFFIELD(cammac_3, krb5_cammac, other_verifiers, 3, opt_vmacs_ptr);
static const struct atype_info *cammac_fields[] = {
&k5_atype_cammac_0, &k5_atype_cammac_1, &k5_atype_cammac_2,
&k5_atype_cammac_3
};
DEFSEQTYPE(cammac, krb5_cammac, cammac_fields);

MAKE_ENCODER(encode_krb5_cammac, cammac);
MAKE_DECODER(decode_krb5_cammac, cammac);
25 changes: 25 additions & 0 deletions src/lib/krb5/krb/kfree.c
Original file line number Diff line number Diff line change
Expand Up @@ -831,3 +831,28 @@ k5_free_kkdcp_message(krb5_context context, krb5_kkdcp_message *val)
free(val->kerb_message.data);
free(val);
}

static void
free_vmac(krb5_context context, krb5_verifier_mac *val)
{
if (val == NULL)
return;
krb5_free_principal(context, val->princ);
krb5_free_checksum_contents(context, &val->checksum);
}

void
k5_free_cammac(krb5_context context, krb5_cammac *val)
{
krb5_verifier_mac **vp;

if (val == NULL)
return;
krb5_free_authdata(context, val->elements);
free_vmac(context, val->kdc_verifier);
free_vmac(context, val->svc_verifier);
for (vp = val->other_verifiers; vp != NULL && *vp != NULL; vp++)
free_vmac(context, *vp);
free(val->other_verifiers);
free(val);
}
3 changes: 3 additions & 0 deletions src/lib/krb5/libkrb5.exports
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ decode_krb5_as_rep
decode_krb5_as_req
decode_krb5_authdata
decode_krb5_authenticator
decode_krb5_cammac
decode_krb5_cred
decode_krb5_enc_cred_part
decode_krb5_enc_data
Expand Down Expand Up @@ -56,6 +57,7 @@ encode_krb5_as_rep
encode_krb5_as_req
encode_krb5_authdata
encode_krb5_authenticator
encode_krb5_cammac
encode_krb5_checksum
encode_krb5_cred
encode_krb5_enc_cred_part
Expand Down Expand Up @@ -114,6 +116,7 @@ k5_etypes_contains
k5_expand_path_tokens
k5_expand_path_tokens_extra
k5_free_algorithm_identifier
k5_free_cammac
k5_free_otp_tokeninfo
k5_free_kkdcp_message
k5_free_pa_otp_challenge
Expand Down
3 changes: 2 additions & 1 deletion src/tests/asn.1/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ SRCS= $(srcdir)/krb5_encode_test.c $(srcdir)/krb5_decode_test.c \
$(srcdir)/trval.c $(srcdir)/t_trval.c

ASN1SRCS= $(srcdir)/krb5.asn1 $(srcdir)/pkix.asn1 $(srcdir)/otp.asn1 \
$(srcdir)/pkinit.asn1 $(srcdir)/pkinit-agility.asn1
$(srcdir)/pkinit.asn1 $(srcdir)/pkinit-agility.asn1 \
$(srcdir)/cammac.asn1

all:: krb5_encode_test krb5_decode_test krb5_decode_leak t_trval

Expand Down
30 changes: 30 additions & 0 deletions src/tests/asn.1/cammac.asn1
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
KerberosV5CAMMAC DEFINITIONS EXPLICIT TAGS ::= BEGIN

IMPORTS
AuthorizationData, PrincipalName, Checksum, UInt32, Int32
FROM KerberosV5Spec2 { iso(1) identified-organization(3)
dod(6) internet(1) security(5) kerberosV5(2)
modules(4) krb5spec2(2) };
-- as defined in RFC 4120.

AD-CAMMAC ::= SEQUENCE {
elements [0] AuthorizationData,
kdc-verifier [1] Verifier-MAC OPTIONAL,
svc-verifier [2] Verifier-MAC OPTIONAL,
other-verifiers [3] SEQUENCE (SIZE (1..MAX))
OF Verifier OPTIONAL
}

Verifier ::= CHOICE {
mac Verifier-MAC,
...
}

Verifier-MAC ::= SEQUENCE {
identifier [0] PrincipalName OPTIONAL,
kvno [1] UInt32 OPTIONAL,
enctype [2] Int32 OPTIONAL,
mac [3] Checksum
}

END
13 changes: 13 additions & 0 deletions src/tests/asn.1/krb5_decode_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,19 @@ int main(argc, argv)
decode_run("kkdcp_message","","30 82 01 FC A0 82 01 EC 04 82 01 E8 6A 82 01 E4 30 82 01 E0 A1 03 02 01 05 A2 03 02 01 0A A3 26 30 24 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 30 10 A1 03 02 01 0D A2 09 04 07 70 61 2D 64 61 74 61 A4 82 01 AA 30 82 01 A6 A0 07 03 05 00 FE DC BA 98 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 A2 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A3 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 A4 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A5 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A6 11 18 0F 31 39 39 34 30 36 31 30 30 36 30 33 31 37 5A A7 03 02 01 2A A8 08 30 06 02 01 00 02 01 01 A9 20 30 1E 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 30 0D A0 03 02 01 02 A1 06 04 04 12 D0 00 23 AA 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 AB 81 BF 30 81 BC 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 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 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 61 5C 30 5A A0 03 02 01 05 A1 10 1B 0E 41 54 48 45 4E 41 2E 4D 49 54 2E 45 44 55 A2 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 A3 25 30 23 A0 03 02 01 00 A1 03 02 01 05 A2 17 04 15 6B 72 62 41 53 4E 2E 31 20 74 65 73 74 20 6D 65 73 73 61 67 65 A1 0A 1B 08 6B 72 62 35 64 61 74 61",decode_krb5_kkdcp_message,ktest_equal_kkdcp_message,ktest_free_kkdcp_message);
}

/****************************************************************/
/* decode_krb5_cammac */
{
setup(krb5_cammac,ktest_make_minimal_cammac);
decode_run("cammac","(optionals NULL)","30 12 A0 10 30 0E 30 0C A0 03 02 01 01 A1 05 04 03 61 64 31",decode_krb5_cammac,ktest_equal_cammac,k5_free_cammac);
ktest_empty_cammac(&ref);
}
{
setup(krb5_cammac,ktest_make_maximal_cammac);
decode_run("cammac","","30 81 F2 A0 1E 30 1C 30 0C A0 03 02 01 01 A1 05 04 03 61 64 31 30 0C A0 03 02 01 02 A1 05 04 03 61 64 32 A1 3D 30 3B 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 03 02 01 05 A2 03 02 01 10 A3 13 30 11 A0 03 02 01 01 A1 0A 04 08 63 6B 73 75 6D 6B 64 63 A2 3D 30 3B 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 03 02 01 05 A2 03 02 01 10 A3 13 30 11 A0 03 02 01 01 A1 0A 04 08 63 6B 73 75 6D 73 76 63 A3 52 30 50 30 13 A3 11 30 0F A0 03 02 01 01 A1 08 04 06 63 6B 73 75 6D 31 30 39 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 03 02 01 05 A2 03 02 01 10 A3 11 30 0F A0 03 02 01 01 A1 08 04 06 63 6B 73 75 6D 32",decode_krb5_cammac,ktest_equal_cammac,k5_free_cammac);
ktest_empty_cammac(&ref);
}

#ifndef DISABLE_PKINIT

/****************************************************************/
Expand Down
10 changes: 10 additions & 0 deletions src/tests/asn.1/krb5_encode_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,16 @@ main(argc, argv)
encode_run(info, "kkdcp_message", "", encode_krb5_kkdcp_message);
ktest_empty_kkdcp_message(&info);
}
/* encode_krb5_cammac */
{
krb5_cammac req;
ktest_make_minimal_cammac(&req);
encode_run(req, "cammac", "(optionals NULL)", encode_krb5_cammac);
ktest_empty_cammac(&req);
ktest_make_maximal_cammac(&req);
encode_run(req, "cammac", "", encode_krb5_cammac);
ktest_empty_cammac(&req);
}
#ifndef DISABLE_PKINIT
/****************************************************************/
/* encode_krb5_pa_pk_as_req */
Expand Down
86 changes: 86 additions & 0 deletions src/tests/asn.1/ktest.c
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,65 @@ ktest_make_sample_kkdcp_message(krb5_kkdcp_message *p)
p->dclocator_hint = 0;
}

static krb5_authdata *
make_ad_element(krb5_authdatatype ad_type, const char *str)
{
krb5_authdata *ad;

ad = ealloc(sizeof(*ad));
ad->ad_type = ad_type;
ad->length = strlen(str);
ad->contents = ealloc(ad->length);
memcpy(ad->contents, str, ad->length);
return ad;
}

static krb5_verifier_mac *
make_vmac(krb5_boolean include_princ, krb5_kvno kvno, krb5_enctype enctype,
const char *cksumstr)
{
krb5_verifier_mac *vmac;

vmac = ealloc(sizeof(*vmac));
if (include_princ) {
ktest_make_sample_principal(&vmac->princ);
(void)krb5_set_principal_realm(NULL, vmac->princ, "");
} else {
vmac->princ = NULL;
}
vmac->kvno = kvno;
vmac->enctype = enctype;
vmac->checksum.checksum_type = 1;
vmac->checksum.length = strlen(cksumstr);
vmac->checksum.contents = ealloc(vmac->checksum.length);
memcpy(vmac->checksum.contents, cksumstr, vmac->checksum.length);
return vmac;
}

void
ktest_make_minimal_cammac(krb5_cammac *p)
{
memset(p, 0, sizeof(*p));
p->elements = ealloc(2 * sizeof(*p->elements));
p->elements[0] = make_ad_element(1, "ad1");
p->elements[1] = NULL;
}

void
ktest_make_maximal_cammac(krb5_cammac *p)
{
p->elements = ealloc(3 * sizeof(*p->elements));
p->elements[0] = make_ad_element(1, "ad1");
p->elements[1] = make_ad_element(2, "ad2");
p->elements[2] = NULL;
p->kdc_verifier = make_vmac(TRUE, 5, 16, "cksumkdc");
p->svc_verifier = make_vmac(TRUE, 5, 16, "cksumsvc");
p->other_verifiers = ealloc(3 * sizeof(*p->other_verifiers));
p->other_verifiers[0] = make_vmac(FALSE, 0, 0, "cksum1");
p->other_verifiers[1] = make_vmac(TRUE, 5, 16, "cksum2");
p->other_verifiers[2] = NULL;
}

/****************************************************************/
/* destructors */

Expand Down Expand Up @@ -1099,6 +1158,8 @@ ktest_destroy_principal(krb5_principal *p)
{
int i;

if (*p == NULL)
return;
for (i=0; i<(*p)->length; i++)
ktest_empty_data(&(*p)->data[i]);
ktest_empty_data(&(*p)->realm);
Expand Down Expand Up @@ -1755,3 +1816,28 @@ ktest_empty_kkdcp_message(krb5_kkdcp_message *p)
ktest_empty_data(&p->target_domain);
p->dclocator_hint = -1;
}

static void
destroy_verifier_mac(krb5_verifier_mac **vmac)
{
if (*vmac == NULL)
return;
ktest_destroy_principal(&(*vmac)->princ);
ktest_empty_checksum(&(*vmac)->checksum);
free(*vmac);
*vmac = NULL;
}

void
ktest_empty_cammac(krb5_cammac *p)
{
krb5_verifier_mac **vmacp;

ktest_destroy_authorization_data(&p->elements);
destroy_verifier_mac(&p->kdc_verifier);
destroy_verifier_mac(&p->svc_verifier);
for (vmacp = p->other_verifiers; vmacp != NULL && *vmacp != NULL; vmacp++)
destroy_verifier_mac(vmacp);
free(p->other_verifiers);
p->other_verifiers = NULL;
}
3 changes: 3 additions & 0 deletions src/tests/asn.1/ktest.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ void ktest_make_sample_ldap_seqof_key_data(ldap_seqof_key_data *p);
#endif

void ktest_make_sample_kkdcp_message(krb5_kkdcp_message *p);
void ktest_make_minimal_cammac(krb5_cammac *p);
void ktest_make_maximal_cammac(krb5_cammac *p);

/*----------------------------------------------------------------------*/

Expand Down Expand Up @@ -204,6 +206,7 @@ void ktest_empty_ldap_seqof_key_data(krb5_context, ldap_seqof_key_data *p);
#endif

void ktest_empty_kkdcp_message(krb5_kkdcp_message *p);
void ktest_empty_cammac(krb5_cammac *p);

extern krb5_context test_context;
extern char *sample_principal_name;
Expand Down

0 comments on commit 6a06997

Please sign in to comment.