| OLD | NEW |
| (Empty) |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 4 | |
| 5 /* | |
| 6 * Support routines for PKCS7 implementation, none of which are exported. | |
| 7 * This file should only contain things that are needed by both the | |
| 8 * encoding/creation side *and* the decoding/decryption side. Anything | |
| 9 * else should be static routines in the appropriate file. | |
| 10 * | |
| 11 * $Id: p7local.c,v 1.16 2012/04/25 14:50:06 gerv%gerv.net Exp $ | |
| 12 */ | |
| 13 | |
| 14 #include "p7local.h" | |
| 15 | |
| 16 #include "cryptohi.h" | |
| 17 #include "secasn1.h" | |
| 18 #include "secoid.h" | |
| 19 #include "secitem.h" | |
| 20 #include "pk11func.h" | |
| 21 #include "secpkcs5.h" | |
| 22 #include "secerr.h" | |
| 23 | |
| 24 /* | |
| 25 * ------------------------------------------------------------------- | |
| 26 * Cipher stuff. | |
| 27 */ | |
| 28 | |
| 29 typedef SECStatus (*sec_pkcs7_cipher_function) (void *, | |
| 30 unsigned char *, | |
| 31 unsigned *, | |
| 32 unsigned int, | |
| 33 const unsigned char *, | |
| 34 unsigned int); | |
| 35 typedef SECStatus (*sec_pkcs7_cipher_destroy) (void *, PRBool); | |
| 36 | |
| 37 #define BLOCK_SIZE 4096 | |
| 38 | |
| 39 struct sec_pkcs7_cipher_object { | |
| 40 void *cx; | |
| 41 sec_pkcs7_cipher_function doit; | |
| 42 sec_pkcs7_cipher_destroy destroy; | |
| 43 PRBool encrypt; | |
| 44 int block_size; | |
| 45 int pad_size; | |
| 46 int pending_count; | |
| 47 unsigned char pending_buf[BLOCK_SIZE]; | |
| 48 }; | |
| 49 | |
| 50 SEC_ASN1_MKSUB(CERT_IssuerAndSNTemplate) | |
| 51 SEC_ASN1_MKSUB(CERT_SetOfSignedCrlTemplate) | |
| 52 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) | |
| 53 SEC_ASN1_MKSUB(SEC_OctetStringTemplate) | |
| 54 SEC_ASN1_MKSUB(SEC_SetOfAnyTemplate) | |
| 55 | |
| 56 /* | |
| 57 * Create a cipher object to do decryption, based on the given bulk | |
| 58 * encryption key and algorithm identifier (which may include an iv). | |
| 59 * | |
| 60 * XXX This interface, or one similar, would be really nice available | |
| 61 * in general... I tried to keep the pkcs7-specific stuff (mostly | |
| 62 * having to do with padding) out of here. | |
| 63 * | |
| 64 * XXX Once both are working, it might be nice to combine this and the | |
| 65 * function below (for starting up encryption) into one routine, and just | |
| 66 * have two simple cover functions which call it. | |
| 67 */ | |
| 68 sec_PKCS7CipherObject * | |
| 69 sec_PKCS7CreateDecryptObject (PK11SymKey *key, SECAlgorithmID *algid) | |
| 70 { | |
| 71 sec_PKCS7CipherObject *result; | |
| 72 SECOidTag algtag; | |
| 73 void *ciphercx; | |
| 74 CK_MECHANISM_TYPE cryptoMechType; | |
| 75 PK11SlotInfo *slot; | |
| 76 SECItem *param = NULL; | |
| 77 | |
| 78 result = (struct sec_pkcs7_cipher_object*) | |
| 79 PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object)); | |
| 80 if (result == NULL) | |
| 81 return NULL; | |
| 82 | |
| 83 ciphercx = NULL; | |
| 84 algtag = SECOID_GetAlgorithmTag (algid); | |
| 85 | |
| 86 if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { | |
| 87 SECItem *pwitem; | |
| 88 | |
| 89 pwitem = (SECItem *)PK11_GetSymKeyUserData(key); | |
| 90 if (!pwitem) { | |
| 91 PORT_Free(result); | |
| 92 return NULL; | |
| 93 } | |
| 94 | |
| 95 cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); | |
| 96 if (cryptoMechType == CKM_INVALID_MECHANISM) { | |
| 97 PORT_Free(result); | |
| 98 SECITEM_FreeItem(param,PR_TRUE); | |
| 99 return NULL; | |
| 100 } | |
| 101 } else { | |
| 102 cryptoMechType = PK11_AlgtagToMechanism(algtag); | |
| 103 param = PK11_ParamFromAlgid(algid); | |
| 104 if (param == NULL) { | |
| 105 PORT_Free(result); | |
| 106 return NULL; | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 result->pad_size = PK11_GetBlockSize(cryptoMechType, param); | |
| 111 slot = PK11_GetSlotFromKey(key); | |
| 112 result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size; | |
| 113 PK11_FreeSlot(slot); | |
| 114 ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT, | |
| 115 key, param); | |
| 116 SECITEM_FreeItem(param,PR_TRUE); | |
| 117 if (ciphercx == NULL) { | |
| 118 PORT_Free (result); | |
| 119 return NULL; | |
| 120 } | |
| 121 | |
| 122 result->cx = ciphercx; | |
| 123 result->doit = (sec_pkcs7_cipher_function) PK11_CipherOp; | |
| 124 result->destroy = (sec_pkcs7_cipher_destroy) PK11_DestroyContext; | |
| 125 result->encrypt = PR_FALSE; | |
| 126 result->pending_count = 0; | |
| 127 | |
| 128 return result; | |
| 129 } | |
| 130 | |
| 131 /* | |
| 132 * Create a cipher object to do encryption, based on the given bulk | |
| 133 * encryption key and algorithm tag. Fill in the algorithm identifier | |
| 134 * (which may include an iv) appropriately. | |
| 135 * | |
| 136 * XXX This interface, or one similar, would be really nice available | |
| 137 * in general... I tried to keep the pkcs7-specific stuff (mostly | |
| 138 * having to do with padding) out of here. | |
| 139 * | |
| 140 * XXX Once both are working, it might be nice to combine this and the | |
| 141 * function above (for starting up decryption) into one routine, and just | |
| 142 * have two simple cover functions which call it. | |
| 143 */ | |
| 144 sec_PKCS7CipherObject * | |
| 145 sec_PKCS7CreateEncryptObject (PRArenaPool *poolp, PK11SymKey *key, | |
| 146 SECOidTag algtag, SECAlgorithmID *algid) | |
| 147 { | |
| 148 sec_PKCS7CipherObject *result; | |
| 149 void *ciphercx; | |
| 150 SECStatus rv; | |
| 151 CK_MECHANISM_TYPE cryptoMechType; | |
| 152 PK11SlotInfo *slot; | |
| 153 SECItem *param = NULL; | |
| 154 PRBool needToEncodeAlgid = PR_FALSE; | |
| 155 | |
| 156 result = (struct sec_pkcs7_cipher_object*) | |
| 157 PORT_ZAlloc (sizeof(struct sec_pkcs7_cipher_object)); | |
| 158 if (result == NULL) | |
| 159 return NULL; | |
| 160 | |
| 161 ciphercx = NULL; | |
| 162 if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) { | |
| 163 SECItem *pwitem; | |
| 164 | |
| 165 pwitem = (SECItem *)PK11_GetSymKeyUserData(key); | |
| 166 if (!pwitem) { | |
| 167 PORT_Free(result); | |
| 168 return NULL; | |
| 169 } | |
| 170 | |
| 171 cryptoMechType = PK11_GetPBECryptoMechanism(algid, ¶m, pwitem); | |
| 172 if (cryptoMechType == CKM_INVALID_MECHANISM) { | |
| 173 PORT_Free(result); | |
| 174 SECITEM_FreeItem(param,PR_TRUE); | |
| 175 return NULL; | |
| 176 } | |
| 177 } else { | |
| 178 cryptoMechType = PK11_AlgtagToMechanism(algtag); | |
| 179 param = PK11_GenerateNewParam(cryptoMechType, key); | |
| 180 if (param == NULL) { | |
| 181 PORT_Free(result); | |
| 182 return NULL; | |
| 183 } | |
| 184 needToEncodeAlgid = PR_TRUE; | |
| 185 } | |
| 186 | |
| 187 result->pad_size = PK11_GetBlockSize(cryptoMechType,param); | |
| 188 slot = PK11_GetSlotFromKey(key); | |
| 189 result->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : result->pad_size; | |
| 190 PK11_FreeSlot(slot); | |
| 191 ciphercx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT, | |
| 192 key, param); | |
| 193 if (ciphercx == NULL) { | |
| 194 PORT_Free (result); | |
| 195 SECITEM_FreeItem(param,PR_TRUE); | |
| 196 return NULL; | |
| 197 } | |
| 198 | |
| 199 /* | |
| 200 * These are placed after the CreateContextBySymKey() because some | |
| 201 * mechanisms have to generate their IVs from their card (i.e. FORTEZZA). | |
| 202 * Don't move it from here. | |
| 203 */ | |
| 204 if (needToEncodeAlgid) { | |
| 205 rv = PK11_ParamToAlgid(algtag,param,poolp,algid); | |
| 206 if(rv != SECSuccess) { | |
| 207 PORT_Free (result); | |
| 208 SECITEM_FreeItem(param,PR_TRUE); | |
| 209 return NULL; | |
| 210 } | |
| 211 } | |
| 212 SECITEM_FreeItem(param,PR_TRUE); | |
| 213 | |
| 214 result->cx = ciphercx; | |
| 215 result->doit = (sec_pkcs7_cipher_function) PK11_CipherOp; | |
| 216 result->destroy = (sec_pkcs7_cipher_destroy) PK11_DestroyContext; | |
| 217 result->encrypt = PR_TRUE; | |
| 218 result->pending_count = 0; | |
| 219 | |
| 220 return result; | |
| 221 } | |
| 222 | |
| 223 | |
| 224 /* | |
| 225 * Destroy the cipher object. | |
| 226 */ | |
| 227 static void | |
| 228 sec_pkcs7_destroy_cipher (sec_PKCS7CipherObject *obj) | |
| 229 { | |
| 230 (* obj->destroy) (obj->cx, PR_TRUE); | |
| 231 PORT_Free (obj); | |
| 232 } | |
| 233 | |
| 234 void | |
| 235 sec_PKCS7DestroyDecryptObject (sec_PKCS7CipherObject *obj) | |
| 236 { | |
| 237 PORT_Assert (obj != NULL); | |
| 238 if (obj == NULL) | |
| 239 return; | |
| 240 PORT_Assert (! obj->encrypt); | |
| 241 sec_pkcs7_destroy_cipher (obj); | |
| 242 } | |
| 243 | |
| 244 void | |
| 245 sec_PKCS7DestroyEncryptObject (sec_PKCS7CipherObject *obj) | |
| 246 { | |
| 247 PORT_Assert (obj != NULL); | |
| 248 if (obj == NULL) | |
| 249 return; | |
| 250 PORT_Assert (obj->encrypt); | |
| 251 sec_pkcs7_destroy_cipher (obj); | |
| 252 } | |
| 253 | |
| 254 | |
| 255 /* | |
| 256 * XXX I think all of the following lengths should be longs instead | |
| 257 * of ints, but our current crypto interface uses ints, so I did too. | |
| 258 */ | |
| 259 | |
| 260 | |
| 261 /* | |
| 262 * What will be the output length of the next call to decrypt? | |
| 263 * Result can be used to perform memory allocations. Note that the amount | |
| 264 * is exactly accurate only when not doing a block cipher or when final | |
| 265 * is false, otherwise it is an upper bound on the amount because until | |
| 266 * we see the data we do not know how many padding bytes there are | |
| 267 * (always between 1 and bsize). | |
| 268 * | |
| 269 * Note that this can return zero, which does not mean that the decrypt | |
| 270 * operation can be skipped! (It simply means that there are not enough | |
| 271 * bytes to make up an entire block; the bytes will be reserved until | |
| 272 * there are enough to encrypt/decrypt at least one block.) However, | |
| 273 * if zero is returned it *does* mean that no output buffer need be | |
| 274 * passed in to the subsequent decrypt operation, as no output bytes | |
| 275 * will be stored. | |
| 276 */ | |
| 277 unsigned int | |
| 278 sec_PKCS7DecryptLength (sec_PKCS7CipherObject *obj, unsigned int input_len, | |
| 279 PRBool final) | |
| 280 { | |
| 281 int blocks, block_size; | |
| 282 | |
| 283 PORT_Assert (! obj->encrypt); | |
| 284 | |
| 285 block_size = obj->block_size; | |
| 286 | |
| 287 /* | |
| 288 * If this is not a block cipher, then we always have the same | |
| 289 * number of output bytes as we had input bytes. | |
| 290 */ | |
| 291 if (block_size == 0) | |
| 292 return input_len; | |
| 293 | |
| 294 /* | |
| 295 * On the final call, we will always use up all of the pending | |
| 296 * bytes plus all of the input bytes, *but*, there will be padding | |
| 297 * at the end and we cannot predict how many bytes of padding we | |
| 298 * will end up removing. The amount given here is actually known | |
| 299 * to be at least 1 byte too long (because we know we will have | |
| 300 * at least 1 byte of padding), but seemed clearer/better to me. | |
| 301 */ | |
| 302 if (final) | |
| 303 return obj->pending_count + input_len; | |
| 304 | |
| 305 /* | |
| 306 * Okay, this amount is exactly what we will output on the | |
| 307 * next cipher operation. We will always hang onto the last | |
| 308 * 1 - block_size bytes for non-final operations. That is, | |
| 309 * we will do as many complete blocks as we can *except* the | |
| 310 * last block (complete or partial). (This is because until | |
| 311 * we know we are at the end, we cannot know when to interpret | |
| 312 * and removing the padding byte(s), which are guaranteed to | |
| 313 * be there.) | |
| 314 */ | |
| 315 blocks = (obj->pending_count + input_len - 1) / block_size; | |
| 316 return blocks * block_size; | |
| 317 } | |
| 318 | |
| 319 /* | |
| 320 * What will be the output length of the next call to encrypt? | |
| 321 * Result can be used to perform memory allocations. | |
| 322 * | |
| 323 * Note that this can return zero, which does not mean that the encrypt | |
| 324 * operation can be skipped! (It simply means that there are not enough | |
| 325 * bytes to make up an entire block; the bytes will be reserved until | |
| 326 * there are enough to encrypt/decrypt at least one block.) However, | |
| 327 * if zero is returned it *does* mean that no output buffer need be | |
| 328 * passed in to the subsequent encrypt operation, as no output bytes | |
| 329 * will be stored. | |
| 330 */ | |
| 331 unsigned int | |
| 332 sec_PKCS7EncryptLength (sec_PKCS7CipherObject *obj, unsigned int input_len, | |
| 333 PRBool final) | |
| 334 { | |
| 335 int blocks, block_size; | |
| 336 int pad_size; | |
| 337 | |
| 338 PORT_Assert (obj->encrypt); | |
| 339 | |
| 340 block_size = obj->block_size; | |
| 341 pad_size = obj->pad_size; | |
| 342 | |
| 343 /* | |
| 344 * If this is not a block cipher, then we always have the same | |
| 345 * number of output bytes as we had input bytes. | |
| 346 */ | |
| 347 if (block_size == 0) | |
| 348 return input_len; | |
| 349 | |
| 350 /* | |
| 351 * On the final call, we only send out what we need for | |
| 352 * remaining bytes plus the padding. (There is always padding, | |
| 353 * so even if we have an exact number of blocks as input, we | |
| 354 * will add another full block that is just padding.) | |
| 355 */ | |
| 356 if (final) { | |
| 357 if (pad_size == 0) { | |
| 358 return obj->pending_count + input_len; | |
| 359 } else { | |
| 360 blocks = (obj->pending_count + input_len) / pad_size; | |
| 361 blocks++; | |
| 362 return blocks*pad_size; | |
| 363 } | |
| 364 } | |
| 365 | |
| 366 /* | |
| 367 * Now, count the number of complete blocks of data we have. | |
| 368 */ | |
| 369 blocks = (obj->pending_count + input_len) / block_size; | |
| 370 | |
| 371 | |
| 372 return blocks * block_size; | |
| 373 } | |
| 374 | |
| 375 | |
| 376 /* | |
| 377 * Decrypt a given length of input buffer (starting at "input" and | |
| 378 * containing "input_len" bytes), placing the decrypted bytes in | |
| 379 * "output" and storing the output length in "*output_len_p". | |
| 380 * "obj" is the return value from sec_PKCS7CreateDecryptObject. | |
| 381 * When "final" is true, this is the last of the data to be decrypted. | |
| 382 * | |
| 383 * This is much more complicated than it sounds when the cipher is | |
| 384 * a block-type, meaning that the decryption function will only | |
| 385 * operate on whole blocks. But our caller is operating stream-wise, | |
| 386 * and can pass in any number of bytes. So we need to keep track | |
| 387 * of block boundaries. We save excess bytes between calls in "obj". | |
| 388 * We also need to determine which bytes are padding, and remove | |
| 389 * them from the output. We can only do this step when we know we | |
| 390 * have the final block of data. PKCS #7 specifies that the padding | |
| 391 * used for a block cipher is a string of bytes, each of whose value is | |
| 392 * the same as the length of the padding, and that all data is padded. | |
| 393 * (Even data that starts out with an exact multiple of blocks gets | |
| 394 * added to it another block, all of which is padding.) | |
| 395 */ | |
| 396 SECStatus | |
| 397 sec_PKCS7Decrypt (sec_PKCS7CipherObject *obj, unsigned char *output, | |
| 398 unsigned int *output_len_p, unsigned int max_output_len, | |
| 399 const unsigned char *input, unsigned int input_len, | |
| 400 PRBool final) | |
| 401 { | |
| 402 int blocks, bsize, pcount, padsize; | |
| 403 unsigned int max_needed, ifraglen, ofraglen, output_len; | |
| 404 unsigned char *pbuf; | |
| 405 SECStatus rv; | |
| 406 | |
| 407 PORT_Assert (! obj->encrypt); | |
| 408 | |
| 409 /* | |
| 410 * Check that we have enough room for the output. Our caller should | |
| 411 * already handle this; failure is really an internal error (i.e. bug). | |
| 412 */ | |
| 413 max_needed = sec_PKCS7DecryptLength (obj, input_len, final); | |
| 414 PORT_Assert (max_output_len >= max_needed); | |
| 415 if (max_output_len < max_needed) { | |
| 416 /* PORT_SetError (XXX); */ | |
| 417 return SECFailure; | |
| 418 } | |
| 419 | |
| 420 /* | |
| 421 * hardware encryption does not like small decryption sizes here, so we | |
| 422 * allow both blocking and padding. | |
| 423 */ | |
| 424 bsize = obj->block_size; | |
| 425 padsize = obj->pad_size; | |
| 426 | |
| 427 /* | |
| 428 * When no blocking or padding work to do, we can simply call the | |
| 429 * cipher function and we are done. | |
| 430 */ | |
| 431 if (bsize == 0) { | |
| 432 return (* obj->doit) (obj->cx, output, output_len_p, max_output_len, | |
| 433 input, input_len); | |
| 434 } | |
| 435 | |
| 436 pcount = obj->pending_count; | |
| 437 pbuf = obj->pending_buf; | |
| 438 | |
| 439 output_len = 0; | |
| 440 | |
| 441 if (pcount) { | |
| 442 /* | |
| 443 * Try to fill in an entire block, starting with the bytes | |
| 444 * we already have saved away. | |
| 445 */ | |
| 446 while (input_len && pcount < bsize) { | |
| 447 pbuf[pcount++] = *input++; | |
| 448 input_len--; | |
| 449 } | |
| 450 /* | |
| 451 * If we have at most a whole block and this is not our last call, | |
| 452 * then we are done for now. (We do not try to decrypt a lone | |
| 453 * single block because we cannot interpret the padding bytes | |
| 454 * until we know we are handling the very last block of all input.) | |
| 455 */ | |
| 456 if (input_len == 0 && !final) { | |
| 457 obj->pending_count = pcount; | |
| 458 if (output_len_p) | |
| 459 *output_len_p = 0; | |
| 460 return SECSuccess; | |
| 461 } | |
| 462 /* | |
| 463 * Given the logic above, we expect to have a full block by now. | |
| 464 * If we do not, there is something wrong, either with our own | |
| 465 * logic or with (length of) the data given to us. | |
| 466 */ | |
| 467 PORT_Assert ((padsize == 0) || (pcount % padsize) == 0); | |
| 468 if ((padsize != 0) && (pcount % padsize) != 0) { | |
| 469 PORT_Assert (final); | |
| 470 PORT_SetError (SEC_ERROR_BAD_DATA); | |
| 471 return SECFailure; | |
| 472 } | |
| 473 /* | |
| 474 * Decrypt the block. | |
| 475 */ | |
| 476 rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len, | |
| 477 pbuf, pcount); | |
| 478 if (rv != SECSuccess) | |
| 479 return rv; | |
| 480 | |
| 481 /* | |
| 482 * For now anyway, all of our ciphers have the same number of | |
| 483 * bytes of output as they do input. If this ever becomes untrue, | |
| 484 * then sec_PKCS7DecryptLength needs to be made smarter! | |
| 485 */ | |
| 486 PORT_Assert (ofraglen == pcount); | |
| 487 | |
| 488 /* | |
| 489 * Account for the bytes now in output. | |
| 490 */ | |
| 491 max_output_len -= ofraglen; | |
| 492 output_len += ofraglen; | |
| 493 output += ofraglen; | |
| 494 } | |
| 495 | |
| 496 /* | |
| 497 * If this is our last call, we expect to have an exact number of | |
| 498 * blocks left to be decrypted; we will decrypt them all. | |
| 499 * | |
| 500 * If not our last call, we always save between 1 and bsize bytes | |
| 501 * until next time. (We must do this because we cannot be sure | |
| 502 * that none of the decrypted bytes are padding bytes until we | |
| 503 * have at least another whole block of data. You cannot tell by | |
| 504 * looking -- the data could be anything -- you can only tell by | |
| 505 * context, knowing you are looking at the last block.) We could | |
| 506 * decrypt a whole block now but it is easier if we just treat it | |
| 507 * the same way we treat partial block bytes. | |
| 508 */ | |
| 509 if (final) { | |
| 510 if (padsize) { | |
| 511 blocks = input_len / padsize; | |
| 512 ifraglen = blocks * padsize; | |
| 513 } else ifraglen = input_len; | |
| 514 PORT_Assert (ifraglen == input_len); | |
| 515 | |
| 516 if (ifraglen != input_len) { | |
| 517 PORT_SetError (SEC_ERROR_BAD_DATA); | |
| 518 return SECFailure; | |
| 519 } | |
| 520 } else { | |
| 521 blocks = (input_len - 1) / bsize; | |
| 522 ifraglen = blocks * bsize; | |
| 523 PORT_Assert (ifraglen < input_len); | |
| 524 | |
| 525 pcount = input_len - ifraglen; | |
| 526 PORT_Memcpy (pbuf, input + ifraglen, pcount); | |
| 527 obj->pending_count = pcount; | |
| 528 } | |
| 529 | |
| 530 if (ifraglen) { | |
| 531 rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len, | |
| 532 input, ifraglen); | |
| 533 if (rv != SECSuccess) | |
| 534 return rv; | |
| 535 | |
| 536 /* | |
| 537 * For now anyway, all of our ciphers have the same number of | |
| 538 * bytes of output as they do input. If this ever becomes untrue, | |
| 539 * then sec_PKCS7DecryptLength needs to be made smarter! | |
| 540 */ | |
| 541 PORT_Assert (ifraglen == ofraglen); | |
| 542 if (ifraglen != ofraglen) { | |
| 543 PORT_SetError (SEC_ERROR_BAD_DATA); | |
| 544 return SECFailure; | |
| 545 } | |
| 546 | |
| 547 output_len += ofraglen; | |
| 548 } else { | |
| 549 ofraglen = 0; | |
| 550 } | |
| 551 | |
| 552 /* | |
| 553 * If we just did our very last block, "remove" the padding by | |
| 554 * adjusting the output length. | |
| 555 */ | |
| 556 if (final && (padsize != 0)) { | |
| 557 unsigned int padlen = *(output + ofraglen - 1); | |
| 558 if (padlen == 0 || padlen > padsize) { | |
| 559 PORT_SetError (SEC_ERROR_BAD_DATA); | |
| 560 return SECFailure; | |
| 561 } | |
| 562 output_len -= padlen; | |
| 563 } | |
| 564 | |
| 565 PORT_Assert (output_len_p != NULL || output_len == 0); | |
| 566 if (output_len_p != NULL) | |
| 567 *output_len_p = output_len; | |
| 568 | |
| 569 return SECSuccess; | |
| 570 } | |
| 571 | |
| 572 /* | |
| 573 * Encrypt a given length of input buffer (starting at "input" and | |
| 574 * containing "input_len" bytes), placing the encrypted bytes in | |
| 575 * "output" and storing the output length in "*output_len_p". | |
| 576 * "obj" is the return value from sec_PKCS7CreateEncryptObject. | |
| 577 * When "final" is true, this is the last of the data to be encrypted. | |
| 578 * | |
| 579 * This is much more complicated than it sounds when the cipher is | |
| 580 * a block-type, meaning that the encryption function will only | |
| 581 * operate on whole blocks. But our caller is operating stream-wise, | |
| 582 * and can pass in any number of bytes. So we need to keep track | |
| 583 * of block boundaries. We save excess bytes between calls in "obj". | |
| 584 * We also need to add padding bytes at the end. PKCS #7 specifies | |
| 585 * that the padding used for a block cipher is a string of bytes, | |
| 586 * each of whose value is the same as the length of the padding, | |
| 587 * and that all data is padded. (Even data that starts out with | |
| 588 * an exact multiple of blocks gets added to it another block, | |
| 589 * all of which is padding.) | |
| 590 * | |
| 591 * XXX I would kind of like to combine this with the function above | |
| 592 * which does decryption, since they have a lot in common. But the | |
| 593 * tricky parts about padding and filling blocks would be much | |
| 594 * harder to read that way, so I left them separate. At least for | |
| 595 * now until it is clear that they are right. | |
| 596 */ | |
| 597 SECStatus | |
| 598 sec_PKCS7Encrypt (sec_PKCS7CipherObject *obj, unsigned char *output, | |
| 599 unsigned int *output_len_p, unsigned int max_output_len, | |
| 600 const unsigned char *input, unsigned int input_len, | |
| 601 PRBool final) | |
| 602 { | |
| 603 int blocks, bsize, padlen, pcount, padsize; | |
| 604 unsigned int max_needed, ifraglen, ofraglen, output_len; | |
| 605 unsigned char *pbuf; | |
| 606 SECStatus rv; | |
| 607 | |
| 608 PORT_Assert (obj->encrypt); | |
| 609 | |
| 610 /* | |
| 611 * Check that we have enough room for the output. Our caller should | |
| 612 * already handle this; failure is really an internal error (i.e. bug). | |
| 613 */ | |
| 614 max_needed = sec_PKCS7EncryptLength (obj, input_len, final); | |
| 615 PORT_Assert (max_output_len >= max_needed); | |
| 616 if (max_output_len < max_needed) { | |
| 617 /* PORT_SetError (XXX); */ | |
| 618 return SECFailure; | |
| 619 } | |
| 620 | |
| 621 bsize = obj->block_size; | |
| 622 padsize = obj->pad_size; | |
| 623 | |
| 624 /* | |
| 625 * When no blocking and padding work to do, we can simply call the | |
| 626 * cipher function and we are done. | |
| 627 */ | |
| 628 if (bsize == 0) { | |
| 629 return (* obj->doit) (obj->cx, output, output_len_p, max_output_len, | |
| 630 input, input_len); | |
| 631 } | |
| 632 | |
| 633 pcount = obj->pending_count; | |
| 634 pbuf = obj->pending_buf; | |
| 635 | |
| 636 output_len = 0; | |
| 637 | |
| 638 if (pcount) { | |
| 639 /* | |
| 640 * Try to fill in an entire block, starting with the bytes | |
| 641 * we already have saved away. | |
| 642 */ | |
| 643 while (input_len && pcount < bsize) { | |
| 644 pbuf[pcount++] = *input++; | |
| 645 input_len--; | |
| 646 } | |
| 647 /* | |
| 648 * If we do not have a full block and we know we will be | |
| 649 * called again, then we are done for now. | |
| 650 */ | |
| 651 if (pcount < bsize && !final) { | |
| 652 obj->pending_count = pcount; | |
| 653 if (output_len_p != NULL) | |
| 654 *output_len_p = 0; | |
| 655 return SECSuccess; | |
| 656 } | |
| 657 /* | |
| 658 * If we have a whole block available, encrypt it. | |
| 659 */ | |
| 660 if ((padsize == 0) || (pcount % padsize) == 0) { | |
| 661 rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len, | |
| 662 pbuf, pcount); | |
| 663 if (rv != SECSuccess) | |
| 664 return rv; | |
| 665 | |
| 666 /* | |
| 667 * For now anyway, all of our ciphers have the same number of | |
| 668 * bytes of output as they do input. If this ever becomes untrue, | |
| 669 * then sec_PKCS7EncryptLength needs to be made smarter! | |
| 670 */ | |
| 671 PORT_Assert (ofraglen == pcount); | |
| 672 | |
| 673 /* | |
| 674 * Account for the bytes now in output. | |
| 675 */ | |
| 676 max_output_len -= ofraglen; | |
| 677 output_len += ofraglen; | |
| 678 output += ofraglen; | |
| 679 | |
| 680 pcount = 0; | |
| 681 } | |
| 682 } | |
| 683 | |
| 684 if (input_len) { | |
| 685 PORT_Assert (pcount == 0); | |
| 686 | |
| 687 blocks = input_len / bsize; | |
| 688 ifraglen = blocks * bsize; | |
| 689 | |
| 690 if (ifraglen) { | |
| 691 rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len, | |
| 692 input, ifraglen); | |
| 693 if (rv != SECSuccess) | |
| 694 return rv; | |
| 695 | |
| 696 /* | |
| 697 * For now anyway, all of our ciphers have the same number of | |
| 698 * bytes of output as they do input. If this ever becomes untrue, | |
| 699 * then sec_PKCS7EncryptLength needs to be made smarter! | |
| 700 */ | |
| 701 PORT_Assert (ifraglen == ofraglen); | |
| 702 | |
| 703 max_output_len -= ofraglen; | |
| 704 output_len += ofraglen; | |
| 705 output += ofraglen; | |
| 706 } | |
| 707 | |
| 708 pcount = input_len - ifraglen; | |
| 709 PORT_Assert (pcount < bsize); | |
| 710 if (pcount) | |
| 711 PORT_Memcpy (pbuf, input + ifraglen, pcount); | |
| 712 } | |
| 713 | |
| 714 if (final) { | |
| 715 padlen = padsize - (pcount % padsize); | |
| 716 PORT_Memset (pbuf + pcount, padlen, padlen); | |
| 717 rv = (* obj->doit) (obj->cx, output, &ofraglen, max_output_len, | |
| 718 pbuf, pcount+padlen); | |
| 719 if (rv != SECSuccess) | |
| 720 return rv; | |
| 721 | |
| 722 /* | |
| 723 * For now anyway, all of our ciphers have the same number of | |
| 724 * bytes of output as they do input. If this ever becomes untrue, | |
| 725 * then sec_PKCS7EncryptLength needs to be made smarter! | |
| 726 */ | |
| 727 PORT_Assert (ofraglen == (pcount+padlen)); | |
| 728 output_len += ofraglen; | |
| 729 } else { | |
| 730 obj->pending_count = pcount; | |
| 731 } | |
| 732 | |
| 733 PORT_Assert (output_len_p != NULL || output_len == 0); | |
| 734 if (output_len_p != NULL) | |
| 735 *output_len_p = output_len; | |
| 736 | |
| 737 return SECSuccess; | |
| 738 } | |
| 739 | |
| 740 /* | |
| 741 * End of cipher stuff. | |
| 742 * ------------------------------------------------------------------- | |
| 743 */ | |
| 744 | |
| 745 | |
| 746 /* | |
| 747 * ------------------------------------------------------------------- | |
| 748 * XXX The following Attribute stuff really belongs elsewhere. | |
| 749 * The Attribute type is *not* part of pkcs7 but rather X.501. | |
| 750 * But for now, since PKCS7 is the only customer of attributes, | |
| 751 * we define them here. Once there is a use outside of PKCS7, | |
| 752 * then change the attribute types and functions from internal | |
| 753 * to external naming convention, and move them elsewhere! | |
| 754 */ | |
| 755 | |
| 756 /* | |
| 757 * Look through a set of attributes and find one that matches the | |
| 758 * specified object ID. If "only" is true, then make sure that | |
| 759 * there is not more than one attribute of the same type. Otherwise, | |
| 760 * just return the first one found. (XXX Does anybody really want | |
| 761 * that first-found behavior? It was like that when I found it...) | |
| 762 */ | |
| 763 SEC_PKCS7Attribute * | |
| 764 sec_PKCS7FindAttribute (SEC_PKCS7Attribute **attrs, SECOidTag oidtag, | |
| 765 PRBool only) | |
| 766 { | |
| 767 SECOidData *oid; | |
| 768 SEC_PKCS7Attribute *attr1, *attr2; | |
| 769 | |
| 770 if (attrs == NULL) | |
| 771 return NULL; | |
| 772 | |
| 773 oid = SECOID_FindOIDByTag(oidtag); | |
| 774 if (oid == NULL) | |
| 775 return NULL; | |
| 776 | |
| 777 while ((attr1 = *attrs++) != NULL) { | |
| 778 if (attr1->type.len == oid->oid.len && PORT_Memcmp (attr1->type.data, | |
| 779 oid->oid.data, | |
| 780 oid->oid.len) == 0) | |
| 781 break; | |
| 782 } | |
| 783 | |
| 784 if (attr1 == NULL) | |
| 785 return NULL; | |
| 786 | |
| 787 if (!only) | |
| 788 return attr1; | |
| 789 | |
| 790 while ((attr2 = *attrs++) != NULL) { | |
| 791 if (attr2->type.len == oid->oid.len && PORT_Memcmp (attr2->type.data, | |
| 792 oid->oid.data, | |
| 793 oid->oid.len) == 0) | |
| 794 break; | |
| 795 } | |
| 796 | |
| 797 if (attr2 != NULL) | |
| 798 return NULL; | |
| 799 | |
| 800 return attr1; | |
| 801 } | |
| 802 | |
| 803 | |
| 804 /* | |
| 805 * Return the single attribute value, doing some sanity checking first: | |
| 806 * - Multiple values are *not* expected. | |
| 807 * - Empty values are *not* expected. | |
| 808 */ | |
| 809 SECItem * | |
| 810 sec_PKCS7AttributeValue(SEC_PKCS7Attribute *attr) | |
| 811 { | |
| 812 SECItem *value; | |
| 813 | |
| 814 if (attr == NULL) | |
| 815 return NULL; | |
| 816 | |
| 817 value = attr->values[0]; | |
| 818 | |
| 819 if (value == NULL || value->data == NULL || value->len == 0) | |
| 820 return NULL; | |
| 821 | |
| 822 if (attr->values[1] != NULL) | |
| 823 return NULL; | |
| 824 | |
| 825 return value; | |
| 826 } | |
| 827 | |
| 828 static const SEC_ASN1Template * | |
| 829 sec_attr_choose_attr_value_template(void *src_or_dest, PRBool encoding) | |
| 830 { | |
| 831 const SEC_ASN1Template *theTemplate; | |
| 832 | |
| 833 SEC_PKCS7Attribute *attribute; | |
| 834 SECOidData *oiddata; | |
| 835 PRBool encoded; | |
| 836 | |
| 837 PORT_Assert (src_or_dest != NULL); | |
| 838 if (src_or_dest == NULL) | |
| 839 return NULL; | |
| 840 | |
| 841 attribute = (SEC_PKCS7Attribute*)src_or_dest; | |
| 842 | |
| 843 if (encoding && attribute->encoded) | |
| 844 return SEC_ASN1_GET(SEC_AnyTemplate); | |
| 845 | |
| 846 oiddata = attribute->typeTag; | |
| 847 if (oiddata == NULL) { | |
| 848 oiddata = SECOID_FindOID(&attribute->type); | |
| 849 attribute->typeTag = oiddata; | |
| 850 } | |
| 851 | |
| 852 if (oiddata == NULL) { | |
| 853 encoded = PR_TRUE; | |
| 854 theTemplate = SEC_ASN1_GET(SEC_AnyTemplate); | |
| 855 } else { | |
| 856 switch (oiddata->offset) { | |
| 857 default: | |
| 858 encoded = PR_TRUE; | |
| 859 theTemplate = SEC_ASN1_GET(SEC_AnyTemplate); | |
| 860 break; | |
| 861 case SEC_OID_PKCS9_EMAIL_ADDRESS: | |
| 862 case SEC_OID_RFC1274_MAIL: | |
| 863 case SEC_OID_PKCS9_UNSTRUCTURED_NAME: | |
| 864 encoded = PR_FALSE; | |
| 865 theTemplate = SEC_ASN1_GET(SEC_IA5StringTemplate); | |
| 866 break; | |
| 867 case SEC_OID_PKCS9_CONTENT_TYPE: | |
| 868 encoded = PR_FALSE; | |
| 869 theTemplate = SEC_ASN1_GET(SEC_ObjectIDTemplate); | |
| 870 break; | |
| 871 case SEC_OID_PKCS9_MESSAGE_DIGEST: | |
| 872 encoded = PR_FALSE; | |
| 873 theTemplate = SEC_ASN1_GET(SEC_OctetStringTemplate); | |
| 874 break; | |
| 875 case SEC_OID_PKCS9_SIGNING_TIME: | |
| 876 encoded = PR_FALSE; | |
| 877 theTemplate = SEC_ASN1_GET(CERT_TimeChoiceTemplate); | |
| 878 break; | |
| 879 /* XXX Want other types here, too */ | |
| 880 } | |
| 881 } | |
| 882 | |
| 883 if (encoding) { | |
| 884 /* | |
| 885 * If we are encoding and we think we have an already-encoded value, | |
| 886 * then the code which initialized this attribute should have set | |
| 887 * the "encoded" property to true (and we would have returned early, | |
| 888 * up above). No devastating error, but that code should be fixed. | |
| 889 * (It could indicate that the resulting encoded bytes are wrong.) | |
| 890 */ | |
| 891 PORT_Assert (!encoded); | |
| 892 } else { | |
| 893 /* | |
| 894 * We are decoding; record whether the resulting value is | |
| 895 * still encoded or not. | |
| 896 */ | |
| 897 attribute->encoded = encoded; | |
| 898 } | |
| 899 return theTemplate; | |
| 900 } | |
| 901 | |
| 902 static const SEC_ASN1TemplateChooserPtr sec_attr_chooser | |
| 903 = sec_attr_choose_attr_value_template; | |
| 904 | |
| 905 static const SEC_ASN1Template sec_pkcs7_attribute_template[] = { | |
| 906 { SEC_ASN1_SEQUENCE, | |
| 907 0, NULL, sizeof(SEC_PKCS7Attribute) }, | |
| 908 { SEC_ASN1_OBJECT_ID, | |
| 909 offsetof(SEC_PKCS7Attribute,type) }, | |
| 910 { SEC_ASN1_DYNAMIC | SEC_ASN1_SET_OF, | |
| 911 offsetof(SEC_PKCS7Attribute,values), | |
| 912 &sec_attr_chooser }, | |
| 913 { 0 } | |
| 914 }; | |
| 915 | |
| 916 static const SEC_ASN1Template sec_pkcs7_set_of_attribute_template[] = { | |
| 917 { SEC_ASN1_SET_OF, 0, sec_pkcs7_attribute_template }, | |
| 918 }; | |
| 919 | |
| 920 /* | |
| 921 * If you are wondering why this routine does not reorder the attributes | |
| 922 * first, and might be tempted to make it do so, see the comment by the | |
| 923 * call to ReorderAttributes in p7encode.c. (Or, see who else calls this | |
| 924 * and think long and hard about the implications of making it always | |
| 925 * do the reordering.) | |
| 926 */ | |
| 927 SECItem * | |
| 928 sec_PKCS7EncodeAttributes (PRArenaPool *poolp, SECItem *dest, void *src) | |
| 929 { | |
| 930 return SEC_ASN1EncodeItem (poolp, dest, src, | |
| 931 sec_pkcs7_set_of_attribute_template); | |
| 932 } | |
| 933 | |
| 934 /* | |
| 935 * Make sure that the order of the attributes guarantees valid DER | |
| 936 * (which must be in lexigraphically ascending order for a SET OF); | |
| 937 * if reordering is necessary it will be done in place (in attrs). | |
| 938 */ | |
| 939 SECStatus | |
| 940 sec_PKCS7ReorderAttributes (SEC_PKCS7Attribute **attrs) | |
| 941 { | |
| 942 PRArenaPool *poolp; | |
| 943 int num_attrs, i, pass, besti; | |
| 944 unsigned int j; | |
| 945 SECItem **enc_attrs; | |
| 946 SEC_PKCS7Attribute **new_attrs; | |
| 947 | |
| 948 /* | |
| 949 * I think we should not be called with NULL. But if we are, | |
| 950 * call it a success anyway, because the order *is* okay. | |
| 951 */ | |
| 952 PORT_Assert (attrs != NULL); | |
| 953 if (attrs == NULL) | |
| 954 return SECSuccess; | |
| 955 | |
| 956 /* | |
| 957 * Count how many attributes we are dealing with here. | |
| 958 */ | |
| 959 num_attrs = 0; | |
| 960 while (attrs[num_attrs] != NULL) | |
| 961 num_attrs++; | |
| 962 | |
| 963 /* | |
| 964 * Again, I think we should have some attributes here. | |
| 965 * But if we do not, or if there is only one, then call it | |
| 966 * a success because it also already has a fine order. | |
| 967 */ | |
| 968 PORT_Assert (num_attrs); | |
| 969 if (num_attrs == 0 || num_attrs == 1) | |
| 970 return SECSuccess; | |
| 971 | |
| 972 /* | |
| 973 * Allocate an arena for us to work with, so it is easy to | |
| 974 * clean up all of the memory (fairly small pieces, really). | |
| 975 */ | |
| 976 poolp = PORT_NewArena (1024); /* XXX what is right value? */ | |
| 977 if (poolp == NULL) | |
| 978 return SECFailure; /* no memory; nothing we can do... */ | |
| 979 | |
| 980 /* | |
| 981 * Allocate arrays to hold the individual encodings which we will use | |
| 982 * for comparisons and the reordered attributes as they are sorted. | |
| 983 */ | |
| 984 enc_attrs=(SECItem**)PORT_ArenaZAlloc(poolp, num_attrs*sizeof(SECItem *)); | |
| 985 new_attrs = (SEC_PKCS7Attribute**)PORT_ArenaZAlloc (poolp, | |
| 986 num_attrs * sizeof(SEC_PKCS7Attribute *)); | |
| 987 if (enc_attrs == NULL || new_attrs == NULL) { | |
| 988 PORT_FreeArena (poolp, PR_FALSE); | |
| 989 return SECFailure; | |
| 990 } | |
| 991 | |
| 992 /* | |
| 993 * DER encode each individual attribute. | |
| 994 */ | |
| 995 for (i = 0; i < num_attrs; i++) { | |
| 996 enc_attrs[i] = SEC_ASN1EncodeItem (poolp, NULL, attrs[i], | |
| 997 sec_pkcs7_attribute_template); | |
| 998 if (enc_attrs[i] == NULL) { | |
| 999 PORT_FreeArena (poolp, PR_FALSE); | |
| 1000 return SECFailure; | |
| 1001 } | |
| 1002 } | |
| 1003 | |
| 1004 /* | |
| 1005 * Now compare and sort them; this is not the most efficient sorting | |
| 1006 * method, but it is just fine for the problem at hand, because the | |
| 1007 * number of attributes is (always) going to be small. | |
| 1008 */ | |
| 1009 for (pass = 0; pass < num_attrs; pass++) { | |
| 1010 /* | |
| 1011 * Find the first not-yet-accepted attribute. (Once one is | |
| 1012 * sorted into the other array, it is cleared from enc_attrs.) | |
| 1013 */ | |
| 1014 for (i = 0; i < num_attrs; i++) { | |
| 1015 if (enc_attrs[i] != NULL) | |
| 1016 break; | |
| 1017 } | |
| 1018 PORT_Assert (i < num_attrs); | |
| 1019 besti = i; | |
| 1020 | |
| 1021 /* | |
| 1022 * Find the lowest (lexigraphically) encoding. One that is | |
| 1023 * shorter than all the rest is known to be "less" because each | |
| 1024 * attribute is of the same type (a SEQUENCE) and so thus the | |
| 1025 * first octet of each is the same, and the second octet is | |
| 1026 * the length (or the length of the length with the high bit | |
| 1027 * set, followed by the length, which also works out to always | |
| 1028 * order the shorter first). Two (or more) that have the | |
| 1029 * same length need to be compared byte by byte until a mismatch | |
| 1030 * is found. | |
| 1031 */ | |
| 1032 for (i = besti + 1; i < num_attrs; i++) { | |
| 1033 if (enc_attrs[i] == NULL) /* slot already handled */ | |
| 1034 continue; | |
| 1035 | |
| 1036 if (enc_attrs[i]->len != enc_attrs[besti]->len) { | |
| 1037 if (enc_attrs[i]->len < enc_attrs[besti]->len) | |
| 1038 besti = i; | |
| 1039 continue; | |
| 1040 } | |
| 1041 | |
| 1042 for (j = 0; j < enc_attrs[i]->len; j++) { | |
| 1043 if (enc_attrs[i]->data[j] < enc_attrs[besti]->data[j]) { | |
| 1044 besti = i; | |
| 1045 break; | |
| 1046 } | |
| 1047 } | |
| 1048 | |
| 1049 /* | |
| 1050 * For this not to be true, we would have to have encountered | |
| 1051 * two *identical* attributes, which I think we should not see. | |
| 1052 * So assert if it happens, but even if it does, let it go | |
| 1053 * through; the ordering of the two does not matter. | |
| 1054 */ | |
| 1055 PORT_Assert (j < enc_attrs[i]->len); | |
| 1056 } | |
| 1057 | |
| 1058 /* | |
| 1059 * Now we have found the next-lowest one; copy it over and | |
| 1060 * remove it from enc_attrs. | |
| 1061 */ | |
| 1062 new_attrs[pass] = attrs[besti]; | |
| 1063 enc_attrs[besti] = NULL; | |
| 1064 } | |
| 1065 | |
| 1066 /* | |
| 1067 * Now new_attrs has the attributes in the order we want; | |
| 1068 * copy them back into the attrs array we started with. | |
| 1069 */ | |
| 1070 for (i = 0; i < num_attrs; i++) | |
| 1071 attrs[i] = new_attrs[i]; | |
| 1072 | |
| 1073 PORT_FreeArena (poolp, PR_FALSE); | |
| 1074 return SECSuccess; | |
| 1075 } | |
| 1076 | |
| 1077 /* | |
| 1078 * End of attribute stuff. | |
| 1079 * ------------------------------------------------------------------- | |
| 1080 */ | |
| 1081 | |
| 1082 | |
| 1083 /* | |
| 1084 * Templates and stuff. Keep these at the end of the file. | |
| 1085 */ | |
| 1086 | |
| 1087 /* forward declaration */ | |
| 1088 static const SEC_ASN1Template * | |
| 1089 sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding); | |
| 1090 | |
| 1091 static const SEC_ASN1TemplateChooserPtr sec_pkcs7_chooser | |
| 1092 = sec_pkcs7_choose_content_template; | |
| 1093 | |
| 1094 const SEC_ASN1Template sec_PKCS7ContentInfoTemplate[] = { | |
| 1095 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, | |
| 1096 0, NULL, sizeof(SEC_PKCS7ContentInfo) }, | |
| 1097 { SEC_ASN1_OBJECT_ID, | |
| 1098 offsetof(SEC_PKCS7ContentInfo,contentType) }, | |
| 1099 { SEC_ASN1_OPTIONAL | SEC_ASN1_DYNAMIC | SEC_ASN1_MAY_STREAM | |
| 1100 | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
| 1101 offsetof(SEC_PKCS7ContentInfo,content), | |
| 1102 &sec_pkcs7_chooser }, | |
| 1103 { 0 } | |
| 1104 }; | |
| 1105 | |
| 1106 /* XXX These names should change from external to internal convention. */ | |
| 1107 | |
| 1108 static const SEC_ASN1Template SEC_PKCS7SignerInfoTemplate[] = { | |
| 1109 { SEC_ASN1_SEQUENCE, | |
| 1110 0, NULL, sizeof(SEC_PKCS7SignerInfo) }, | |
| 1111 { SEC_ASN1_INTEGER, | |
| 1112 offsetof(SEC_PKCS7SignerInfo,version) }, | |
| 1113 { SEC_ASN1_POINTER | SEC_ASN1_XTRN, | |
| 1114 offsetof(SEC_PKCS7SignerInfo,issuerAndSN), | |
| 1115 SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) }, | |
| 1116 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
| 1117 offsetof(SEC_PKCS7SignerInfo,digestAlg), | |
| 1118 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 1119 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, | |
| 1120 offsetof(SEC_PKCS7SignerInfo,authAttr), | |
| 1121 sec_pkcs7_set_of_attribute_template }, | |
| 1122 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
| 1123 offsetof(SEC_PKCS7SignerInfo,digestEncAlg), | |
| 1124 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 1125 { SEC_ASN1_OCTET_STRING, | |
| 1126 offsetof(SEC_PKCS7SignerInfo,encDigest) }, | |
| 1127 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, | |
| 1128 offsetof(SEC_PKCS7SignerInfo,unAuthAttr), | |
| 1129 sec_pkcs7_set_of_attribute_template }, | |
| 1130 { 0 } | |
| 1131 }; | |
| 1132 | |
| 1133 static const SEC_ASN1Template SEC_PKCS7SignedDataTemplate[] = { | |
| 1134 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, | |
| 1135 0, NULL, sizeof(SEC_PKCS7SignedData) }, | |
| 1136 { SEC_ASN1_INTEGER, | |
| 1137 offsetof(SEC_PKCS7SignedData,version) }, | |
| 1138 { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, | |
| 1139 offsetof(SEC_PKCS7SignedData,digestAlgorithms), | |
| 1140 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 1141 { SEC_ASN1_INLINE, | |
| 1142 offsetof(SEC_PKCS7SignedData,contentInfo), | |
| 1143 sec_PKCS7ContentInfoTemplate }, | |
| 1144 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | | |
| 1145 SEC_ASN1_XTRN | 0, | |
| 1146 offsetof(SEC_PKCS7SignedData,rawCerts), | |
| 1147 SEC_ASN1_SUB(SEC_SetOfAnyTemplate) }, | |
| 1148 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | | |
| 1149 SEC_ASN1_XTRN | 1, | |
| 1150 offsetof(SEC_PKCS7SignedData,crls), | |
| 1151 SEC_ASN1_SUB(CERT_SetOfSignedCrlTemplate) }, | |
| 1152 { SEC_ASN1_SET_OF, | |
| 1153 offsetof(SEC_PKCS7SignedData,signerInfos), | |
| 1154 SEC_PKCS7SignerInfoTemplate }, | |
| 1155 { 0 } | |
| 1156 }; | |
| 1157 | |
| 1158 static const SEC_ASN1Template SEC_PointerToPKCS7SignedDataTemplate[] = { | |
| 1159 { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedDataTemplate } | |
| 1160 }; | |
| 1161 | |
| 1162 static const SEC_ASN1Template SEC_PKCS7RecipientInfoTemplate[] = { | |
| 1163 { SEC_ASN1_SEQUENCE, | |
| 1164 0, NULL, sizeof(SEC_PKCS7RecipientInfo) }, | |
| 1165 { SEC_ASN1_INTEGER, | |
| 1166 offsetof(SEC_PKCS7RecipientInfo,version) }, | |
| 1167 { SEC_ASN1_POINTER | SEC_ASN1_XTRN, | |
| 1168 offsetof(SEC_PKCS7RecipientInfo,issuerAndSN), | |
| 1169 SEC_ASN1_SUB(CERT_IssuerAndSNTemplate) }, | |
| 1170 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
| 1171 offsetof(SEC_PKCS7RecipientInfo,keyEncAlg), | |
| 1172 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 1173 { SEC_ASN1_OCTET_STRING, | |
| 1174 offsetof(SEC_PKCS7RecipientInfo,encKey) }, | |
| 1175 { 0 } | |
| 1176 }; | |
| 1177 | |
| 1178 static const SEC_ASN1Template SEC_PKCS7EncryptedContentInfoTemplate[] = { | |
| 1179 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, | |
| 1180 0, NULL, sizeof(SEC_PKCS7EncryptedContentInfo) }, | |
| 1181 { SEC_ASN1_OBJECT_ID, | |
| 1182 offsetof(SEC_PKCS7EncryptedContentInfo,contentType) }, | |
| 1183 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
| 1184 offsetof(SEC_PKCS7EncryptedContentInfo,contentEncAlg), | |
| 1185 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 1186 { SEC_ASN1_OPTIONAL | SEC_ASN1_MAY_STREAM | SEC_ASN1_CONTEXT_SPECIFIC | | |
| 1187 SEC_ASN1_XTRN | 0, | |
| 1188 offsetof(SEC_PKCS7EncryptedContentInfo,encContent), | |
| 1189 SEC_ASN1_SUB(SEC_OctetStringTemplate) }, | |
| 1190 { 0 } | |
| 1191 }; | |
| 1192 | |
| 1193 static const SEC_ASN1Template SEC_PKCS7EnvelopedDataTemplate[] = { | |
| 1194 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, | |
| 1195 0, NULL, sizeof(SEC_PKCS7EnvelopedData) }, | |
| 1196 { SEC_ASN1_INTEGER, | |
| 1197 offsetof(SEC_PKCS7EnvelopedData,version) }, | |
| 1198 { SEC_ASN1_SET_OF, | |
| 1199 offsetof(SEC_PKCS7EnvelopedData,recipientInfos), | |
| 1200 SEC_PKCS7RecipientInfoTemplate }, | |
| 1201 { SEC_ASN1_INLINE, | |
| 1202 offsetof(SEC_PKCS7EnvelopedData,encContentInfo), | |
| 1203 SEC_PKCS7EncryptedContentInfoTemplate }, | |
| 1204 { 0 } | |
| 1205 }; | |
| 1206 | |
| 1207 static const SEC_ASN1Template SEC_PointerToPKCS7EnvelopedDataTemplate[] = { | |
| 1208 { SEC_ASN1_POINTER, 0, SEC_PKCS7EnvelopedDataTemplate } | |
| 1209 }; | |
| 1210 | |
| 1211 static const SEC_ASN1Template SEC_PKCS7SignedAndEnvelopedDataTemplate[] = { | |
| 1212 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, | |
| 1213 0, NULL, sizeof(SEC_PKCS7SignedAndEnvelopedData) }, | |
| 1214 { SEC_ASN1_INTEGER, | |
| 1215 offsetof(SEC_PKCS7SignedAndEnvelopedData,version) }, | |
| 1216 { SEC_ASN1_SET_OF, | |
| 1217 offsetof(SEC_PKCS7SignedAndEnvelopedData,recipientInfos), | |
| 1218 SEC_PKCS7RecipientInfoTemplate }, | |
| 1219 { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, | |
| 1220 offsetof(SEC_PKCS7SignedAndEnvelopedData,digestAlgorithms), | |
| 1221 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 1222 { SEC_ASN1_INLINE, | |
| 1223 offsetof(SEC_PKCS7SignedAndEnvelopedData,encContentInfo), | |
| 1224 SEC_PKCS7EncryptedContentInfoTemplate }, | |
| 1225 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | | |
| 1226 SEC_ASN1_XTRN | 0, | |
| 1227 offsetof(SEC_PKCS7SignedAndEnvelopedData,rawCerts), | |
| 1228 SEC_ASN1_SUB(SEC_SetOfAnyTemplate) }, | |
| 1229 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | | |
| 1230 SEC_ASN1_XTRN | 1, | |
| 1231 offsetof(SEC_PKCS7SignedAndEnvelopedData,crls), | |
| 1232 SEC_ASN1_SUB(CERT_SetOfSignedCrlTemplate) }, | |
| 1233 { SEC_ASN1_SET_OF, | |
| 1234 offsetof(SEC_PKCS7SignedAndEnvelopedData,signerInfos), | |
| 1235 SEC_PKCS7SignerInfoTemplate }, | |
| 1236 { 0 } | |
| 1237 }; | |
| 1238 | |
| 1239 static const SEC_ASN1Template | |
| 1240 SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate[] = { | |
| 1241 { SEC_ASN1_POINTER, 0, SEC_PKCS7SignedAndEnvelopedDataTemplate } | |
| 1242 }; | |
| 1243 | |
| 1244 static const SEC_ASN1Template SEC_PKCS7DigestedDataTemplate[] = { | |
| 1245 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, | |
| 1246 0, NULL, sizeof(SEC_PKCS7DigestedData) }, | |
| 1247 { SEC_ASN1_INTEGER, | |
| 1248 offsetof(SEC_PKCS7DigestedData,version) }, | |
| 1249 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, | |
| 1250 offsetof(SEC_PKCS7DigestedData,digestAlg), | |
| 1251 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | |
| 1252 { SEC_ASN1_INLINE, | |
| 1253 offsetof(SEC_PKCS7DigestedData,contentInfo), | |
| 1254 sec_PKCS7ContentInfoTemplate }, | |
| 1255 { SEC_ASN1_OCTET_STRING, | |
| 1256 offsetof(SEC_PKCS7DigestedData,digest) }, | |
| 1257 { 0 } | |
| 1258 }; | |
| 1259 | |
| 1260 static const SEC_ASN1Template SEC_PointerToPKCS7DigestedDataTemplate[] = { | |
| 1261 { SEC_ASN1_POINTER, 0, SEC_PKCS7DigestedDataTemplate } | |
| 1262 }; | |
| 1263 | |
| 1264 static const SEC_ASN1Template SEC_PKCS7EncryptedDataTemplate[] = { | |
| 1265 { SEC_ASN1_SEQUENCE | SEC_ASN1_MAY_STREAM, | |
| 1266 0, NULL, sizeof(SEC_PKCS7EncryptedData) }, | |
| 1267 { SEC_ASN1_INTEGER, | |
| 1268 offsetof(SEC_PKCS7EncryptedData,version) }, | |
| 1269 { SEC_ASN1_INLINE, | |
| 1270 offsetof(SEC_PKCS7EncryptedData,encContentInfo), | |
| 1271 SEC_PKCS7EncryptedContentInfoTemplate }, | |
| 1272 { 0 } | |
| 1273 }; | |
| 1274 | |
| 1275 static const SEC_ASN1Template SEC_PointerToPKCS7EncryptedDataTemplate[] = { | |
| 1276 { SEC_ASN1_POINTER, 0, SEC_PKCS7EncryptedDataTemplate } | |
| 1277 }; | |
| 1278 | |
| 1279 static const SEC_ASN1Template * | |
| 1280 sec_pkcs7_choose_content_template(void *src_or_dest, PRBool encoding) | |
| 1281 { | |
| 1282 const SEC_ASN1Template *theTemplate; | |
| 1283 SEC_PKCS7ContentInfo *cinfo; | |
| 1284 SECOidTag kind; | |
| 1285 | |
| 1286 PORT_Assert (src_or_dest != NULL); | |
| 1287 if (src_or_dest == NULL) | |
| 1288 return NULL; | |
| 1289 | |
| 1290 cinfo = (SEC_PKCS7ContentInfo*)src_or_dest; | |
| 1291 kind = SEC_PKCS7ContentType (cinfo); | |
| 1292 switch (kind) { | |
| 1293 default: | |
| 1294 theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); | |
| 1295 break; | |
| 1296 case SEC_OID_PKCS7_DATA: | |
| 1297 theTemplate = SEC_ASN1_GET(SEC_PointerToOctetStringTemplate); | |
| 1298 break; | |
| 1299 case SEC_OID_PKCS7_SIGNED_DATA: | |
| 1300 theTemplate = SEC_PointerToPKCS7SignedDataTemplate; | |
| 1301 break; | |
| 1302 case SEC_OID_PKCS7_ENVELOPED_DATA: | |
| 1303 theTemplate = SEC_PointerToPKCS7EnvelopedDataTemplate; | |
| 1304 break; | |
| 1305 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: | |
| 1306 theTemplate = SEC_PointerToPKCS7SignedAndEnvelopedDataTemplate; | |
| 1307 break; | |
| 1308 case SEC_OID_PKCS7_DIGESTED_DATA: | |
| 1309 theTemplate = SEC_PointerToPKCS7DigestedDataTemplate; | |
| 1310 break; | |
| 1311 case SEC_OID_PKCS7_ENCRYPTED_DATA: | |
| 1312 theTemplate = SEC_PointerToPKCS7EncryptedDataTemplate; | |
| 1313 break; | |
| 1314 } | |
| 1315 return theTemplate; | |
| 1316 } | |
| 1317 | |
| 1318 /* | |
| 1319 * End of templates. Do not add stuff after this; put new code | |
| 1320 * up above the start of the template definitions. | |
| 1321 */ | |
| OLD | NEW |