1*54925bf6Swillf #pragma ident "%Z%%M% %I% %E% SMI" 2*54925bf6Swillf 3*54925bf6Swillf /* ... copyright ... */ 4*54925bf6Swillf 5*54925bf6Swillf /* Novell key-format scheme: 6*54925bf6Swillf 7*54925bf6Swillf KrbKeySet ::= SEQUENCE { 8*54925bf6Swillf attribute-major-vno [0] UInt16, 9*54925bf6Swillf attribute-minor-vno [1] UInt16, 10*54925bf6Swillf kvno [2] UInt32, 11*54925bf6Swillf mkvno [3] UInt32 OPTIONAL, 12*54925bf6Swillf keys [4] SEQUENCE OF KrbKey, 13*54925bf6Swillf ... 14*54925bf6Swillf } 15*54925bf6Swillf 16*54925bf6Swillf KrbKey ::= SEQUENCE { 17*54925bf6Swillf salt [0] KrbSalt OPTIONAL, 18*54925bf6Swillf key [1] EncryptionKey, 19*54925bf6Swillf s2kparams [2] OCTET STRING OPTIONAL, 20*54925bf6Swillf ... 21*54925bf6Swillf } 22*54925bf6Swillf 23*54925bf6Swillf KrbSalt ::= SEQUENCE { 24*54925bf6Swillf type [0] Int32, 25*54925bf6Swillf salt [1] OCTET STRING OPTIONAL 26*54925bf6Swillf } 27*54925bf6Swillf 28*54925bf6Swillf EncryptionKey ::= SEQUENCE { 29*54925bf6Swillf keytype [0] Int32, 30*54925bf6Swillf keyvalue [1] OCTET STRING 31*54925bf6Swillf } 32*54925bf6Swillf 33*54925bf6Swillf */ 34*54925bf6Swillf 35*54925bf6Swillf #include <k5-int.h> 36*54925bf6Swillf #include <kdb.h> 37*54925bf6Swillf 38*54925bf6Swillf #include "krbasn1.h" 39*54925bf6Swillf #include "asn1_encode.h" 40*54925bf6Swillf #include "asn1_decode.h" 41*54925bf6Swillf #include "asn1_make.h" 42*54925bf6Swillf #include "asn1_get.h" 43*54925bf6Swillf 44*54925bf6Swillf #define asn1_encode_sequence_of_keys krb5int_ldap_encode_sequence_of_keys 45*54925bf6Swillf #define asn1_decode_sequence_of_keys krb5int_ldap_decode_sequence_of_keys 46*54925bf6Swillf 47*54925bf6Swillf #define cleanup(err) \ 48*54925bf6Swillf { \ 49*54925bf6Swillf ret = err; \ 50*54925bf6Swillf goto last; \ 51*54925bf6Swillf } 52*54925bf6Swillf 53*54925bf6Swillf #define checkerr \ 54*54925bf6Swillf if (ret != 0) \ 55*54925bf6Swillf goto last 56*54925bf6Swillf 57*54925bf6Swillf /************************************************************************/ 58*54925bf6Swillf /* Encode the Principal's keys */ 59*54925bf6Swillf /************************************************************************/ 60*54925bf6Swillf 61*54925bf6Swillf static asn1_error_code 62*54925bf6Swillf asn1_encode_key(asn1buf *buf, 63*54925bf6Swillf krb5_key_data key_data, 64*54925bf6Swillf unsigned int *retlen) 65*54925bf6Swillf { 66*54925bf6Swillf asn1_error_code ret = 0; 67*54925bf6Swillf unsigned int length, sum = 0; 68*54925bf6Swillf 69*54925bf6Swillf /* Encode the key type and value. */ 70*54925bf6Swillf { 71*54925bf6Swillf unsigned int key_len = 0; 72*54925bf6Swillf /* key value */ 73*54925bf6Swillf ret = asn1_encode_octetstring (buf, 74*54925bf6Swillf key_data.key_data_length[0], 75*54925bf6Swillf key_data.key_data_contents[0], 76*54925bf6Swillf &length); checkerr; 77*54925bf6Swillf key_len += length; 78*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length); checkerr; 79*54925bf6Swillf key_len += length; 80*54925bf6Swillf /* key type */ 81*54925bf6Swillf ret = asn1_encode_integer (buf, key_data.key_data_type[0], &length); 82*54925bf6Swillf checkerr; 83*54925bf6Swillf key_len += length; 84*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr; 85*54925bf6Swillf key_len += length; 86*54925bf6Swillf 87*54925bf6Swillf ret = asn1_make_sequence(buf, key_len, &length); checkerr; 88*54925bf6Swillf key_len += length; 89*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, key_len, &length); checkerr; 90*54925bf6Swillf key_len += length; 91*54925bf6Swillf 92*54925bf6Swillf sum += key_len; 93*54925bf6Swillf } 94*54925bf6Swillf /* Encode the salt type and value (optional) */ 95*54925bf6Swillf if (key_data.key_data_ver > 1) { 96*54925bf6Swillf unsigned int salt_len = 0; 97*54925bf6Swillf /* salt value (optional) */ 98*54925bf6Swillf if (key_data.key_data_length[1] > 0) { 99*54925bf6Swillf ret = asn1_encode_octetstring (buf, 100*54925bf6Swillf key_data.key_data_length[1], 101*54925bf6Swillf key_data.key_data_contents[1], 102*54925bf6Swillf &length); checkerr; 103*54925bf6Swillf salt_len += length; 104*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length); 105*54925bf6Swillf checkerr; 106*54925bf6Swillf salt_len += length; 107*54925bf6Swillf } 108*54925bf6Swillf /* salt type */ 109*54925bf6Swillf ret = asn1_encode_integer (buf, key_data.key_data_type[1], &length); 110*54925bf6Swillf checkerr; 111*54925bf6Swillf salt_len += length; 112*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr; 113*54925bf6Swillf salt_len += length; 114*54925bf6Swillf 115*54925bf6Swillf ret = asn1_make_sequence(buf, salt_len, &length); checkerr; 116*54925bf6Swillf salt_len += length; 117*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, salt_len, &length); checkerr; 118*54925bf6Swillf salt_len += length; 119*54925bf6Swillf 120*54925bf6Swillf sum += salt_len; 121*54925bf6Swillf } 122*54925bf6Swillf 123*54925bf6Swillf ret = asn1_make_sequence(buf, sum, &length); checkerr; 124*54925bf6Swillf sum += length; 125*54925bf6Swillf 126*54925bf6Swillf *retlen = sum; 127*54925bf6Swillf 128*54925bf6Swillf last: 129*54925bf6Swillf return ret; 130*54925bf6Swillf } 131*54925bf6Swillf 132*54925bf6Swillf /* Major version and minor version are both '1' - first version */ 133*54925bf6Swillf /* asn1_error_code asn1_encode_sequence_of_keys (krb5_key_data *key_data, */ 134*54925bf6Swillf krb5_error_code 135*54925bf6Swillf asn1_encode_sequence_of_keys (krb5_key_data *key_data, 136*54925bf6Swillf krb5_int16 n_key_data, 137*54925bf6Swillf krb5_int32 mkvno, /* Master key version number */ 138*54925bf6Swillf krb5_data **code) 139*54925bf6Swillf { 140*54925bf6Swillf asn1_error_code ret = 0; 141*54925bf6Swillf asn1buf *buf = NULL; 142*54925bf6Swillf unsigned int length, sum = 0; 143*54925bf6Swillf unsigned long tmp_ul; 144*54925bf6Swillf 145*54925bf6Swillf *code = NULL; 146*54925bf6Swillf 147*54925bf6Swillf if (n_key_data == 0) cleanup (ASN1_MISSING_FIELD); 148*54925bf6Swillf 149*54925bf6Swillf /* Allocate the buffer */ 150*54925bf6Swillf ret = asn1buf_create(&buf); 151*54925bf6Swillf checkerr; 152*54925bf6Swillf 153*54925bf6Swillf /* Sequence of keys */ 154*54925bf6Swillf { 155*54925bf6Swillf int i; 156*54925bf6Swillf unsigned int seq_len = 0; 157*54925bf6Swillf 158*54925bf6Swillf for (i = n_key_data - 1; i >= 0; i--) { 159*54925bf6Swillf ret = asn1_encode_key (buf, key_data[i], &length); checkerr; 160*54925bf6Swillf seq_len += length; 161*54925bf6Swillf } 162*54925bf6Swillf ret = asn1_make_sequence(buf, seq_len, &length); checkerr; 163*54925bf6Swillf seq_len += length; 164*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 4, seq_len, &length); checkerr; 165*54925bf6Swillf seq_len += length; 166*54925bf6Swillf 167*54925bf6Swillf sum += seq_len; 168*54925bf6Swillf } 169*54925bf6Swillf 170*54925bf6Swillf /* mkvno */ 171*54925bf6Swillf if (mkvno < 0) 172*54925bf6Swillf cleanup (ASN1_BAD_FORMAT); 173*54925bf6Swillf tmp_ul = (unsigned long)mkvno; 174*54925bf6Swillf ret = asn1_encode_unsigned_integer (buf, tmp_ul, &length); checkerr; 175*54925bf6Swillf sum += length; 176*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 3, length, &length); checkerr; 177*54925bf6Swillf sum += length; 178*54925bf6Swillf 179*54925bf6Swillf /* kvno (assuming all keys in array have same version) */ 180*54925bf6Swillf if (key_data[0].key_data_kvno < 0) 181*54925bf6Swillf cleanup (ASN1_BAD_FORMAT); 182*54925bf6Swillf tmp_ul = (unsigned long)key_data[0].key_data_kvno; 183*54925bf6Swillf ret = asn1_encode_unsigned_integer (buf, tmp_ul, &length); 184*54925bf6Swillf checkerr; 185*54925bf6Swillf sum += length; 186*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 2, length, &length); checkerr; 187*54925bf6Swillf sum += length; 188*54925bf6Swillf 189*54925bf6Swillf /* attribute-minor-vno == 1 */ 190*54925bf6Swillf ret = asn1_encode_unsigned_integer (buf, 1, &length); checkerr; 191*54925bf6Swillf sum += length; 192*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 1, length, &length); checkerr; 193*54925bf6Swillf sum += length; 194*54925bf6Swillf 195*54925bf6Swillf /* attribute-major-vno == 1 */ 196*54925bf6Swillf ret = asn1_encode_unsigned_integer (buf, 1, &length); checkerr; 197*54925bf6Swillf sum += length; 198*54925bf6Swillf ret = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0, length, &length); checkerr; 199*54925bf6Swillf sum += length; 200*54925bf6Swillf 201*54925bf6Swillf ret = asn1_make_sequence(buf, sum, &length); checkerr; 202*54925bf6Swillf sum += length; 203*54925bf6Swillf 204*54925bf6Swillf /* The reverse encoding is straightened out here */ 205*54925bf6Swillf ret = asn12krb5_buf (buf, code); checkerr; 206*54925bf6Swillf 207*54925bf6Swillf last: 208*54925bf6Swillf asn1buf_destroy (&buf); 209*54925bf6Swillf 210*54925bf6Swillf if (ret != 0 && *code != NULL) { 211*54925bf6Swillf if ((*code)->data != NULL) 212*54925bf6Swillf free ((*code)->data); 213*54925bf6Swillf free (*code); 214*54925bf6Swillf } 215*54925bf6Swillf 216*54925bf6Swillf return ret; 217*54925bf6Swillf } 218*54925bf6Swillf 219*54925bf6Swillf /************************************************************************/ 220*54925bf6Swillf /* Decode the Principal's keys */ 221*54925bf6Swillf /************************************************************************/ 222*54925bf6Swillf 223*54925bf6Swillf #define safe_syncbuf(outer,inner) \ 224*54925bf6Swillf if (! ((inner)->next == (inner)->bound + 1 && \ 225*54925bf6Swillf (inner)->next == (outer)->next + buflen)) \ 226*54925bf6Swillf cleanup (ASN1_BAD_LENGTH); \ 227*54925bf6Swillf asn1buf_sync((outer), (inner), 0, 0, 0, 0, 0); 228*54925bf6Swillf 229*54925bf6Swillf static asn1_error_code 230*54925bf6Swillf decode_tagged_integer (asn1buf *buf, asn1_tagnum expectedtag, long *val) 231*54925bf6Swillf { 232*54925bf6Swillf int buflen; 233*54925bf6Swillf asn1_error_code ret = 0; 234*54925bf6Swillf asn1buf tmp, subbuf; 235*54925bf6Swillf taginfo t; 236*54925bf6Swillf 237*54925bf6Swillf /* Work on a copy of 'buf' */ 238*54925bf6Swillf ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr; 239*54925bf6Swillf ret = asn1_get_tag_2(&tmp, &t); checkerr; 240*54925bf6Swillf if (t.tagnum != expectedtag) 241*54925bf6Swillf cleanup (ASN1_MISSING_FIELD); 242*54925bf6Swillf 243*54925bf6Swillf buflen = t.length; 244*54925bf6Swillf ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr; 245*54925bf6Swillf ret = asn1_decode_integer(&subbuf, val); checkerr; 246*54925bf6Swillf 247*54925bf6Swillf safe_syncbuf(&tmp, &subbuf); 248*54925bf6Swillf *buf = tmp; 249*54925bf6Swillf 250*54925bf6Swillf last: 251*54925bf6Swillf return ret; 252*54925bf6Swillf } 253*54925bf6Swillf 254*54925bf6Swillf #if 0 /* not currently used */ 255*54925bf6Swillf static asn1_error_code 256*54925bf6Swillf decode_tagged_unsigned_integer (asn1buf *buf, int expectedtag, unsigned long *val) 257*54925bf6Swillf { 258*54925bf6Swillf int buflen; 259*54925bf6Swillf asn1_error_code ret = 0; 260*54925bf6Swillf asn1buf tmp, subbuf; 261*54925bf6Swillf taginfo t; 262*54925bf6Swillf 263*54925bf6Swillf /* Work on a copy of 'buf' */ 264*54925bf6Swillf ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr; 265*54925bf6Swillf ret = asn1_get_tag_2(&tmp, &t); checkerr; 266*54925bf6Swillf if (t.tagnum != expectedtag) 267*54925bf6Swillf cleanup (ASN1_MISSING_FIELD); 268*54925bf6Swillf 269*54925bf6Swillf buflen = t.length; 270*54925bf6Swillf ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr; 271*54925bf6Swillf ret = asn1_decode_unsigned_integer(&subbuf, val); checkerr; 272*54925bf6Swillf 273*54925bf6Swillf safe_syncbuf(&tmp, &subbuf); 274*54925bf6Swillf *buf = tmp; 275*54925bf6Swillf 276*54925bf6Swillf last: 277*54925bf6Swillf return ret; 278*54925bf6Swillf } 279*54925bf6Swillf #endif 280*54925bf6Swillf 281*54925bf6Swillf static asn1_error_code 282*54925bf6Swillf decode_tagged_octetstring (asn1buf *buf, asn1_tagnum expectedtag, 283*54925bf6Swillf unsigned int *len, asn1_octet **val) 284*54925bf6Swillf { 285*54925bf6Swillf int buflen; 286*54925bf6Swillf asn1_error_code ret = 0; 287*54925bf6Swillf asn1buf tmp, subbuf; 288*54925bf6Swillf taginfo t; 289*54925bf6Swillf 290*54925bf6Swillf *val = NULL; 291*54925bf6Swillf 292*54925bf6Swillf /* Work on a copy of 'buf' */ 293*54925bf6Swillf ret = asn1buf_imbed(&tmp, buf, 0, 1); checkerr; 294*54925bf6Swillf ret = asn1_get_tag_2(&tmp, &t); checkerr; 295*54925bf6Swillf if (t.tagnum != expectedtag) 296*54925bf6Swillf cleanup (ASN1_MISSING_FIELD); 297*54925bf6Swillf 298*54925bf6Swillf buflen = t.length; 299*54925bf6Swillf ret = asn1buf_imbed(&subbuf, &tmp, t.length, 0); checkerr; 300*54925bf6Swillf ret = asn1_decode_octetstring (&subbuf, len, val); checkerr; 301*54925bf6Swillf 302*54925bf6Swillf safe_syncbuf(&tmp, &subbuf); 303*54925bf6Swillf *buf = tmp; 304*54925bf6Swillf 305*54925bf6Swillf last: 306*54925bf6Swillf if (ret != 0 && *val != NULL) 307*54925bf6Swillf free (*val); 308*54925bf6Swillf return ret; 309*54925bf6Swillf } 310*54925bf6Swillf 311*54925bf6Swillf static asn1_error_code asn1_decode_key(asn1buf *buf, krb5_key_data *key) 312*54925bf6Swillf { 313*54925bf6Swillf int buflen, seqindef; 314*54925bf6Swillf unsigned int length; 315*54925bf6Swillf asn1_error_code ret; 316*54925bf6Swillf asn1buf subbuf; 317*54925bf6Swillf taginfo t; 318*54925bf6Swillf 319*54925bf6Swillf key->key_data_contents[0] = NULL; 320*54925bf6Swillf key->key_data_contents[1] = NULL; 321*54925bf6Swillf 322*54925bf6Swillf ret = asn1_get_sequence(buf, &length, &seqindef); checkerr; 323*54925bf6Swillf buflen = length; 324*54925bf6Swillf ret = asn1buf_imbed(&subbuf, buf, length, seqindef); checkerr; 325*54925bf6Swillf 326*54925bf6Swillf asn1_get_tag_2(&subbuf, &t); 327*54925bf6Swillf /* Salt */ 328*54925bf6Swillf if (t.tagnum == 0) { 329*54925bf6Swillf int buflen; 330*54925bf6Swillf asn1buf slt; 331*54925bf6Swillf unsigned long keytype; 332*54925bf6Swillf unsigned int keylen; 333*54925bf6Swillf 334*54925bf6Swillf key->key_data_ver = 2; 335*54925bf6Swillf asn1_get_sequence(&subbuf, &length, &seqindef); 336*54925bf6Swillf buflen = length; 337*54925bf6Swillf asn1buf_imbed(&slt, &subbuf, length, seqindef); 338*54925bf6Swillf 339*54925bf6Swillf ret = decode_tagged_integer (&slt, 0, (long *) &keytype); 340*54925bf6Swillf key->key_data_type[1] = keytype; /* XXX range check?? */ 341*54925bf6Swillf checkerr; 342*54925bf6Swillf 343*54925bf6Swillf if (asn1buf_remains(&slt, 0) != 0) { /* Salt value is optional */ 344*54925bf6Swillf ret = decode_tagged_octetstring (&slt, 1, &keylen, 345*54925bf6Swillf &key->key_data_contents[1]); checkerr; 346*54925bf6Swillf } 347*54925bf6Swillf safe_syncbuf (&subbuf, &slt); 348*54925bf6Swillf key->key_data_length[1] = keylen; /* XXX range check?? */ 349*54925bf6Swillf 350*54925bf6Swillf ret = asn1_get_tag_2(&subbuf, &t); checkerr; 351*54925bf6Swillf } else 352*54925bf6Swillf key->key_data_ver = 1; 353*54925bf6Swillf 354*54925bf6Swillf /* Key */ 355*54925bf6Swillf { 356*54925bf6Swillf int buflen; 357*54925bf6Swillf asn1buf kbuf; 358*54925bf6Swillf long lval; 359*54925bf6Swillf unsigned int ival; 360*54925bf6Swillf 361*54925bf6Swillf if (t.tagnum != 1) 362*54925bf6Swillf cleanup (ASN1_MISSING_FIELD); 363*54925bf6Swillf 364*54925bf6Swillf ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr; 365*54925bf6Swillf buflen = length; 366*54925bf6Swillf ret = asn1buf_imbed(&kbuf, &subbuf, length, seqindef); checkerr; 367*54925bf6Swillf 368*54925bf6Swillf ret = decode_tagged_integer (&kbuf, 0, &lval); 369*54925bf6Swillf checkerr; 370*54925bf6Swillf key->key_data_type[0] = lval; /* XXX range check? */ 371*54925bf6Swillf 372*54925bf6Swillf ret = decode_tagged_octetstring (&kbuf, 1, &ival, 373*54925bf6Swillf &key->key_data_contents[0]); checkerr; 374*54925bf6Swillf key->key_data_length[0] = ival; /* XXX range check? */ 375*54925bf6Swillf 376*54925bf6Swillf safe_syncbuf (&subbuf, &kbuf); 377*54925bf6Swillf } 378*54925bf6Swillf 379*54925bf6Swillf safe_syncbuf (buf, &subbuf); 380*54925bf6Swillf 381*54925bf6Swillf last: 382*54925bf6Swillf if (ret != 0) { 383*54925bf6Swillf if (key->key_data_contents[0] != NULL) { 384*54925bf6Swillf free (key->key_data_contents[0]); 385*54925bf6Swillf key->key_data_contents[0] = NULL; 386*54925bf6Swillf } 387*54925bf6Swillf if (key->key_data_contents[1] != NULL) { 388*54925bf6Swillf free (key->key_data_contents[1]); 389*54925bf6Swillf key->key_data_contents[1] = NULL; 390*54925bf6Swillf } 391*54925bf6Swillf } 392*54925bf6Swillf return ret; 393*54925bf6Swillf } 394*54925bf6Swillf 395*54925bf6Swillf /* asn1_error_code asn1_decode_sequence_of_keys (krb5_data *in, */ 396*54925bf6Swillf krb5_error_code asn1_decode_sequence_of_keys (krb5_data *in, 397*54925bf6Swillf krb5_key_data **out, 398*54925bf6Swillf krb5_int16 *n_key_data, 399*54925bf6Swillf int *mkvno) 400*54925bf6Swillf { 401*54925bf6Swillf asn1_error_code ret; 402*54925bf6Swillf asn1buf buf, subbuf; 403*54925bf6Swillf int seqindef; 404*54925bf6Swillf unsigned int length; 405*54925bf6Swillf taginfo t; 406*54925bf6Swillf int kvno, maj, min; 407*54925bf6Swillf long lval; 408*54925bf6Swillf 409*54925bf6Swillf *n_key_data = 0; 410*54925bf6Swillf *out = NULL; 411*54925bf6Swillf 412*54925bf6Swillf ret = asn1buf_wrap_data(&buf, in); checkerr; 413*54925bf6Swillf 414*54925bf6Swillf ret = asn1_get_sequence(&buf, &length, &seqindef); checkerr; 415*54925bf6Swillf ret = asn1buf_imbed(&subbuf, &buf, length, seqindef); checkerr; 416*54925bf6Swillf 417*54925bf6Swillf /* attribute-major-vno */ 418*54925bf6Swillf ret = decode_tagged_integer (&subbuf, 0, &lval); checkerr; 419*54925bf6Swillf maj = lval; /* XXX range check? */ 420*54925bf6Swillf 421*54925bf6Swillf /* attribute-minor-vno */ 422*54925bf6Swillf ret = decode_tagged_integer (&subbuf, 1, &lval); checkerr; 423*54925bf6Swillf min = lval; /* XXX range check? */ 424*54925bf6Swillf 425*54925bf6Swillf if (maj != 1 || min != 1) 426*54925bf6Swillf cleanup (ASN1_BAD_FORMAT); 427*54925bf6Swillf 428*54925bf6Swillf /* kvno (assuming all keys in array have same version) */ 429*54925bf6Swillf ret = decode_tagged_integer (&subbuf, 2, &lval); checkerr; 430*54925bf6Swillf kvno = lval; /* XXX range check? */ 431*54925bf6Swillf 432*54925bf6Swillf /* mkvno (optional) */ 433*54925bf6Swillf ret = decode_tagged_integer (&subbuf, 3, &lval); checkerr; 434*54925bf6Swillf *mkvno = lval; /* XXX range check? */ 435*54925bf6Swillf 436*54925bf6Swillf ret = asn1_get_tag_2(&subbuf, &t); checkerr; 437*54925bf6Swillf 438*54925bf6Swillf /* Sequence of keys */ 439*54925bf6Swillf { 440*54925bf6Swillf int i, buflen; 441*54925bf6Swillf asn1buf keyseq; 442*54925bf6Swillf if (t.tagnum != 4) 443*54925bf6Swillf cleanup (ASN1_MISSING_FIELD); 444*54925bf6Swillf ret = asn1_get_sequence(&subbuf, &length, &seqindef); checkerr; 445*54925bf6Swillf buflen = length; 446*54925bf6Swillf ret = asn1buf_imbed(&keyseq, &subbuf, length, seqindef); checkerr; 447*54925bf6Swillf for (i = 1, *out = NULL; ; i++) { 448*54925bf6Swillf krb5_key_data *tmp; 449*54925bf6Swillf tmp = (krb5_key_data *) realloc (*out, i * sizeof (krb5_key_data)); 450*54925bf6Swillf if (tmp == NULL) 451*54925bf6Swillf cleanup (ENOMEM); 452*54925bf6Swillf *out = tmp; 453*54925bf6Swillf (*out)[i - 1].key_data_kvno = kvno; 454*54925bf6Swillf ret = asn1_decode_key(&keyseq, &(*out)[i - 1]); checkerr; 455*54925bf6Swillf (*n_key_data)++; 456*54925bf6Swillf if (asn1buf_remains(&keyseq, 0) == 0) 457*54925bf6Swillf break; /* Not freeing the last key structure */ 458*54925bf6Swillf } 459*54925bf6Swillf safe_syncbuf (&subbuf, &keyseq); 460*54925bf6Swillf } 461*54925bf6Swillf 462*54925bf6Swillf /* 463*54925bf6Swillf * There could be other data inside the outermost sequence ... tags we don't 464*54925bf6Swillf * know about. So, not invoking "safe_syncbuf(&buf,&subbuf)" 465*54925bf6Swillf */ 466*54925bf6Swillf 467*54925bf6Swillf last: 468*54925bf6Swillf if (ret != 0) { 469*54925bf6Swillf int i; 470*54925bf6Swillf for (i = 0; i < *n_key_data; i++) { 471*54925bf6Swillf if ((*out)[i].key_data_contents[0] != NULL) 472*54925bf6Swillf free ((*out)[i].key_data_contents[0]); 473*54925bf6Swillf if ((*out)[i].key_data_contents[1] != NULL) 474*54925bf6Swillf free ((*out)[i].key_data_contents[1]); 475*54925bf6Swillf } 476*54925bf6Swillf free (*out); 477*54925bf6Swillf *out = NULL; 478*54925bf6Swillf } 479*54925bf6Swillf 480*54925bf6Swillf return ret; 481*54925bf6Swillf } 482