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