Implement encoding and decoding for supportedKDFs and kdfID
authorSam Hartman <hartmans@mit.edu>
Mon, 19 Sep 2011 00:51:39 +0000 (00:51 +0000)
committerSam Hartman <hartmans@mit.edu>
Mon, 19 Sep 2011 00:51:39 +0000 (00:51 +0000)
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
src/lib/krb5/asn.1/asn1_k_decode.h
src/lib/krb5/asn.1/asn1_k_decode_kdc.c
src/lib/krb5/asn.1/asn1_k_encode.c
src/plugins/preauth/pkinit/pkinit_lib.c

index e2ba5757f3012a63abaca5c977e390e702074435..599a2159da5c98995c7ad520051fd4dd8affb34f 100644 (file)
@@ -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);
+}
index 8f7bf0ccdf49d56f78161d1f264c69579bdd5619..ed51ab1646861a1ed3572848c1945454d906fb39 100644 (file)
@@ -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
index 1711ca04aef369bc32907a6e48b46b7591549ee5..c0aa2a2c3fb78d27272c611559f8103a8440d5a8 100644 (file)
@@ -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;
index 7bca6d23b682847b213d2c179e3a3b40a3e1591e..9d06de109cfc81930d83a5c325c8cf78d9e7b57a 100644 (file)
@@ -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);
 
index 8eb64019cba532afd055cf3cb0ae0cf8994e3599..034587b138f3fa6e0e5918e8a7d7a4d890ee52d2 100644 (file)
@@ -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