1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pkcs7/p7common.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,691 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * PKCS7 implementation -- the exported parts that are used whether 1.10 + * creating or decoding. 1.11 + */ 1.12 + 1.13 +#include "p7local.h" 1.14 + 1.15 +#include "cert.h" 1.16 +#include "secitem.h" 1.17 +#include "secoid.h" 1.18 +#include "pk11func.h" 1.19 + 1.20 +/* 1.21 + * Find out (saving pointer to lookup result for future reference) 1.22 + * and return the inner content type. 1.23 + */ 1.24 +SECOidTag 1.25 +SEC_PKCS7ContentType (SEC_PKCS7ContentInfo *cinfo) 1.26 +{ 1.27 + if (cinfo->contentTypeTag == NULL) 1.28 + cinfo->contentTypeTag = SECOID_FindOID(&(cinfo->contentType)); 1.29 + 1.30 + if (cinfo->contentTypeTag == NULL) 1.31 + return SEC_OID_UNKNOWN; 1.32 + 1.33 + return cinfo->contentTypeTag->offset; 1.34 +} 1.35 + 1.36 + 1.37 +/* 1.38 + * Destroy a PKCS7 contentInfo and all of its sub-pieces. 1.39 + */ 1.40 +void 1.41 +SEC_PKCS7DestroyContentInfo(SEC_PKCS7ContentInfo *cinfo) 1.42 +{ 1.43 + SECOidTag kind; 1.44 + CERTCertificate **certs; 1.45 + CERTCertificateList **certlists; 1.46 + SEC_PKCS7SignerInfo **signerinfos; 1.47 + SEC_PKCS7RecipientInfo **recipientinfos; 1.48 + 1.49 + PORT_Assert (cinfo->refCount > 0); 1.50 + if (cinfo->refCount <= 0) 1.51 + return; 1.52 + 1.53 + cinfo->refCount--; 1.54 + if (cinfo->refCount > 0) 1.55 + return; 1.56 + 1.57 + certs = NULL; 1.58 + certlists = NULL; 1.59 + recipientinfos = NULL; 1.60 + signerinfos = NULL; 1.61 + 1.62 + kind = SEC_PKCS7ContentType (cinfo); 1.63 + switch (kind) { 1.64 + case SEC_OID_PKCS7_ENVELOPED_DATA: 1.65 + { 1.66 + SEC_PKCS7EnvelopedData *edp; 1.67 + 1.68 + edp = cinfo->content.envelopedData; 1.69 + if (edp != NULL) { 1.70 + recipientinfos = edp->recipientInfos; 1.71 + } 1.72 + } 1.73 + break; 1.74 + case SEC_OID_PKCS7_SIGNED_DATA: 1.75 + { 1.76 + SEC_PKCS7SignedData *sdp; 1.77 + 1.78 + sdp = cinfo->content.signedData; 1.79 + if (sdp != NULL) { 1.80 + certs = sdp->certs; 1.81 + certlists = sdp->certLists; 1.82 + signerinfos = sdp->signerInfos; 1.83 + } 1.84 + } 1.85 + break; 1.86 + case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: 1.87 + { 1.88 + SEC_PKCS7SignedAndEnvelopedData *saedp; 1.89 + 1.90 + saedp = cinfo->content.signedAndEnvelopedData; 1.91 + if (saedp != NULL) { 1.92 + certs = saedp->certs; 1.93 + certlists = saedp->certLists; 1.94 + recipientinfos = saedp->recipientInfos; 1.95 + signerinfos = saedp->signerInfos; 1.96 + if (saedp->sigKey != NULL) 1.97 + PK11_FreeSymKey (saedp->sigKey); 1.98 + } 1.99 + } 1.100 + break; 1.101 + default: 1.102 + /* XXX Anything else that needs to be "manually" freed/destroyed? */ 1.103 + break; 1.104 + } 1.105 + 1.106 + if (certs != NULL) { 1.107 + CERTCertificate *cert; 1.108 + 1.109 + while ((cert = *certs++) != NULL) { 1.110 + CERT_DestroyCertificate (cert); 1.111 + } 1.112 + } 1.113 + 1.114 + if (certlists != NULL) { 1.115 + CERTCertificateList *certlist; 1.116 + 1.117 + while ((certlist = *certlists++) != NULL) { 1.118 + CERT_DestroyCertificateList (certlist); 1.119 + } 1.120 + } 1.121 + 1.122 + if (recipientinfos != NULL) { 1.123 + SEC_PKCS7RecipientInfo *ri; 1.124 + 1.125 + while ((ri = *recipientinfos++) != NULL) { 1.126 + if (ri->cert != NULL) 1.127 + CERT_DestroyCertificate (ri->cert); 1.128 + } 1.129 + } 1.130 + 1.131 + if (signerinfos != NULL) { 1.132 + SEC_PKCS7SignerInfo *si; 1.133 + 1.134 + while ((si = *signerinfos++) != NULL) { 1.135 + if (si->cert != NULL) 1.136 + CERT_DestroyCertificate (si->cert); 1.137 + if (si->certList != NULL) 1.138 + CERT_DestroyCertificateList (si->certList); 1.139 + } 1.140 + } 1.141 + 1.142 + if (cinfo->poolp != NULL) { 1.143 + PORT_FreeArena (cinfo->poolp, PR_FALSE); /* XXX clear it? */ 1.144 + } 1.145 +} 1.146 + 1.147 + 1.148 +/* 1.149 + * Return a copy of the given contentInfo. The copy may be virtual 1.150 + * or may be real -- either way, the result needs to be passed to 1.151 + * SEC_PKCS7DestroyContentInfo later (as does the original). 1.152 + */ 1.153 +SEC_PKCS7ContentInfo * 1.154 +SEC_PKCS7CopyContentInfo(SEC_PKCS7ContentInfo *cinfo) 1.155 +{ 1.156 + if (cinfo == NULL) 1.157 + return NULL; 1.158 + 1.159 + PORT_Assert (cinfo->refCount > 0); 1.160 + 1.161 + if (cinfo->created) { 1.162 + /* 1.163 + * Want to do a real copy of these; otherwise subsequent 1.164 + * changes made to either copy are likely to be a surprise. 1.165 + * XXX I suspect that this will not actually be called for yet, 1.166 + * which is why the assert, so to notice if it is... 1.167 + */ 1.168 + PORT_Assert (0); 1.169 + /* 1.170 + * XXX Create a new pool here, and copy everything from 1.171 + * within. For cert stuff, need to call the appropriate 1.172 + * copy functions, etc. 1.173 + */ 1.174 + } 1.175 + 1.176 + cinfo->refCount++; 1.177 + return cinfo; 1.178 +} 1.179 + 1.180 + 1.181 +/* 1.182 + * Return a pointer to the actual content. In the case of those types 1.183 + * which are encrypted, this returns the *plain* content. 1.184 + * XXX Needs revisiting if/when we handle nested encrypted types. 1.185 + */ 1.186 +SECItem * 1.187 +SEC_PKCS7GetContent(SEC_PKCS7ContentInfo *cinfo) 1.188 +{ 1.189 + SECOidTag kind; 1.190 + 1.191 + kind = SEC_PKCS7ContentType (cinfo); 1.192 + switch (kind) { 1.193 + case SEC_OID_PKCS7_DATA: 1.194 + return cinfo->content.data; 1.195 + case SEC_OID_PKCS7_DIGESTED_DATA: 1.196 + { 1.197 + SEC_PKCS7DigestedData *digd; 1.198 + 1.199 + digd = cinfo->content.digestedData; 1.200 + if (digd == NULL) 1.201 + break; 1.202 + return SEC_PKCS7GetContent (&(digd->contentInfo)); 1.203 + } 1.204 + case SEC_OID_PKCS7_ENCRYPTED_DATA: 1.205 + { 1.206 + SEC_PKCS7EncryptedData *encd; 1.207 + 1.208 + encd = cinfo->content.encryptedData; 1.209 + if (encd == NULL) 1.210 + break; 1.211 + return &(encd->encContentInfo.plainContent); 1.212 + } 1.213 + case SEC_OID_PKCS7_ENVELOPED_DATA: 1.214 + { 1.215 + SEC_PKCS7EnvelopedData *envd; 1.216 + 1.217 + envd = cinfo->content.envelopedData; 1.218 + if (envd == NULL) 1.219 + break; 1.220 + return &(envd->encContentInfo.plainContent); 1.221 + } 1.222 + case SEC_OID_PKCS7_SIGNED_DATA: 1.223 + { 1.224 + SEC_PKCS7SignedData *sigd; 1.225 + 1.226 + sigd = cinfo->content.signedData; 1.227 + if (sigd == NULL) 1.228 + break; 1.229 + return SEC_PKCS7GetContent (&(sigd->contentInfo)); 1.230 + } 1.231 + case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: 1.232 + { 1.233 + SEC_PKCS7SignedAndEnvelopedData *saed; 1.234 + 1.235 + saed = cinfo->content.signedAndEnvelopedData; 1.236 + if (saed == NULL) 1.237 + break; 1.238 + return &(saed->encContentInfo.plainContent); 1.239 + } 1.240 + default: 1.241 + PORT_Assert(0); 1.242 + break; 1.243 + } 1.244 + 1.245 + return NULL; 1.246 +} 1.247 + 1.248 + 1.249 +/* 1.250 + * XXX Fix the placement and formatting of the 1.251 + * following routines (i.e. make them consistent with the rest of 1.252 + * the pkcs7 code -- I think some/many belong in other files and 1.253 + * they all need a formatting/style rehaul) 1.254 + */ 1.255 + 1.256 +/* retrieve the algorithm identifier for encrypted data. 1.257 + * the identifier returned is a copy of the algorithm identifier 1.258 + * in the content info and needs to be freed after being used. 1.259 + * 1.260 + * cinfo is the content info for which to retrieve the 1.261 + * encryption algorithm. 1.262 + * 1.263 + * if the content info is not encrypted data or an error 1.264 + * occurs NULL is returned. 1.265 + */ 1.266 +SECAlgorithmID * 1.267 +SEC_PKCS7GetEncryptionAlgorithm(SEC_PKCS7ContentInfo *cinfo) 1.268 +{ 1.269 + SECAlgorithmID *alg = 0; 1.270 + switch (SEC_PKCS7ContentType(cinfo)) 1.271 + { 1.272 + case SEC_OID_PKCS7_ENCRYPTED_DATA: 1.273 + alg = &cinfo->content.encryptedData->encContentInfo.contentEncAlg; 1.274 + break; 1.275 + case SEC_OID_PKCS7_ENVELOPED_DATA: 1.276 + alg = &cinfo->content.envelopedData->encContentInfo.contentEncAlg; 1.277 + break; 1.278 + case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: 1.279 + alg = &cinfo->content.signedAndEnvelopedData 1.280 + ->encContentInfo.contentEncAlg; 1.281 + break; 1.282 + default: 1.283 + alg = 0; 1.284 + break; 1.285 + } 1.286 + 1.287 + return alg; 1.288 +} 1.289 + 1.290 +/* set the content of the content info. For data content infos, 1.291 + * the data is set. For encrytped content infos, the plainContent 1.292 + * is set, and is expected to be encrypted later. 1.293 + * 1.294 + * cinfo is the content info where the data will be set 1.295 + * 1.296 + * buf is a buffer of the data to set 1.297 + * 1.298 + * len is the length of the data being set. 1.299 + * 1.300 + * in the event of an error, SECFailure is returned. SECSuccess 1.301 + * indicates the content was successfully set. 1.302 + */ 1.303 +SECStatus 1.304 +SEC_PKCS7SetContent(SEC_PKCS7ContentInfo *cinfo, 1.305 + const char *buf, 1.306 + unsigned long len) 1.307 +{ 1.308 + SECOidTag cinfo_type; 1.309 + SECStatus rv; 1.310 + SECItem content; 1.311 + SECOidData *contentTypeTag = NULL; 1.312 + 1.313 + content.type = siBuffer; 1.314 + content.data = (unsigned char *)buf; 1.315 + content.len = len; 1.316 + 1.317 + cinfo_type = SEC_PKCS7ContentType(cinfo); 1.318 + 1.319 + /* set inner content */ 1.320 + switch(cinfo_type) 1.321 + { 1.322 + case SEC_OID_PKCS7_SIGNED_DATA: 1.323 + if(content.len > 0) { 1.324 + /* we "leak" the old content here, but as it's all in the pool */ 1.325 + /* it does not really matter */ 1.326 + 1.327 + /* create content item if necessary */ 1.328 + if (cinfo->content.signedData->contentInfo.content.data == NULL) 1.329 + cinfo->content.signedData->contentInfo.content.data = SECITEM_AllocItem(cinfo->poolp, NULL, 0); 1.330 + rv = SECITEM_CopyItem(cinfo->poolp, 1.331 + cinfo->content.signedData->contentInfo.content.data, 1.332 + &content); 1.333 + } else { 1.334 + cinfo->content.signedData->contentInfo.content.data->data = NULL; 1.335 + cinfo->content.signedData->contentInfo.content.data->len = 0; 1.336 + rv = SECSuccess; 1.337 + } 1.338 + if(rv == SECFailure) 1.339 + goto loser; 1.340 + 1.341 + break; 1.342 + case SEC_OID_PKCS7_ENCRYPTED_DATA: 1.343 + /* XXX this forces the inner content type to be "data" */ 1.344 + /* do we really want to override without asking or reason? */ 1.345 + contentTypeTag = SECOID_FindOIDByTag(SEC_OID_PKCS7_DATA); 1.346 + if(contentTypeTag == NULL) 1.347 + goto loser; 1.348 + rv = SECITEM_CopyItem(cinfo->poolp, 1.349 + &(cinfo->content.encryptedData->encContentInfo.contentType), 1.350 + &(contentTypeTag->oid)); 1.351 + if(rv == SECFailure) 1.352 + goto loser; 1.353 + if(content.len > 0) { 1.354 + rv = SECITEM_CopyItem(cinfo->poolp, 1.355 + &(cinfo->content.encryptedData->encContentInfo.plainContent), 1.356 + &content); 1.357 + } else { 1.358 + cinfo->content.encryptedData->encContentInfo.plainContent.data = NULL; 1.359 + cinfo->content.encryptedData->encContentInfo.encContent.data = NULL; 1.360 + cinfo->content.encryptedData->encContentInfo.plainContent.len = 0; 1.361 + cinfo->content.encryptedData->encContentInfo.encContent.len = 0; 1.362 + rv = SECSuccess; 1.363 + } 1.364 + if(rv == SECFailure) 1.365 + goto loser; 1.366 + break; 1.367 + case SEC_OID_PKCS7_DATA: 1.368 + cinfo->content.data = (SECItem *)PORT_ArenaZAlloc(cinfo->poolp, 1.369 + sizeof(SECItem)); 1.370 + if(cinfo->content.data == NULL) 1.371 + goto loser; 1.372 + if(content.len > 0) { 1.373 + rv = SECITEM_CopyItem(cinfo->poolp, 1.374 + cinfo->content.data, &content); 1.375 + } else { 1.376 + /* handle case with NULL content */ 1.377 + rv = SECSuccess; 1.378 + } 1.379 + if(rv == SECFailure) 1.380 + goto loser; 1.381 + break; 1.382 + default: 1.383 + goto loser; 1.384 + } 1.385 + 1.386 + return SECSuccess; 1.387 + 1.388 +loser: 1.389 + 1.390 + return SECFailure; 1.391 +} 1.392 + 1.393 +/* the content of an encrypted data content info is encrypted. 1.394 + * it is assumed that for encrypted data, that the data has already 1.395 + * been set and is in the "plainContent" field of the content info. 1.396 + * 1.397 + * cinfo is the content info to encrypt 1.398 + * 1.399 + * key is the key with which to perform the encryption. if the 1.400 + * algorithm is a password based encryption algorithm, the 1.401 + * key is actually a password which will be processed per 1.402 + * PKCS #5. 1.403 + * 1.404 + * in the event of an error, SECFailure is returned. SECSuccess 1.405 + * indicates a success. 1.406 + */ 1.407 +SECStatus 1.408 +SEC_PKCS7EncryptContents(PLArenaPool *poolp, 1.409 + SEC_PKCS7ContentInfo *cinfo, 1.410 + SECItem *key, 1.411 + void *wincx) 1.412 +{ 1.413 + SECAlgorithmID *algid = NULL; 1.414 + SECItem * result = NULL; 1.415 + SECItem * src; 1.416 + SECItem * dest; 1.417 + SECItem * blocked_data = NULL; 1.418 + void * mark; 1.419 + void * cx; 1.420 + PK11SymKey * eKey = NULL; 1.421 + PK11SlotInfo * slot = NULL; 1.422 + 1.423 + CK_MECHANISM_TYPE cryptoMechType; 1.424 + int bs; 1.425 + SECStatus rv = SECFailure; 1.426 + SECItem *c_param = NULL; 1.427 + 1.428 + if((cinfo == NULL) || (key == NULL)) 1.429 + return SECFailure; 1.430 + 1.431 + if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA) 1.432 + return SECFailure; 1.433 + 1.434 + algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo); 1.435 + if(algid == NULL) 1.436 + return SECFailure; 1.437 + 1.438 + if(poolp == NULL) 1.439 + poolp = cinfo->poolp; 1.440 + 1.441 + mark = PORT_ArenaMark(poolp); 1.442 + 1.443 + src = &cinfo->content.encryptedData->encContentInfo.plainContent; 1.444 + dest = &cinfo->content.encryptedData->encContentInfo.encContent; 1.445 + dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64)); 1.446 + dest->len = (src->len + 64); 1.447 + if(dest->data == NULL) { 1.448 + rv = SECFailure; 1.449 + goto loser; 1.450 + } 1.451 + 1.452 + slot = PK11_GetInternalKeySlot(); 1.453 + if(slot == NULL) { 1.454 + rv = SECFailure; 1.455 + goto loser; 1.456 + } 1.457 + 1.458 + eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx); 1.459 + if(eKey == NULL) { 1.460 + rv = SECFailure; 1.461 + goto loser; 1.462 + } 1.463 + 1.464 + cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key); 1.465 + if (cryptoMechType == CKM_INVALID_MECHANISM) { 1.466 + rv = SECFailure; 1.467 + goto loser; 1.468 + } 1.469 + 1.470 + /* block according to PKCS 8 */ 1.471 + bs = PK11_GetBlockSize(cryptoMechType, c_param); 1.472 + rv = SECSuccess; 1.473 + if(bs) { 1.474 + char pad_char; 1.475 + pad_char = (char)(bs - (src->len % bs)); 1.476 + if(src->len % bs) { 1.477 + rv = SECSuccess; 1.478 + blocked_data = PK11_BlockData(src, bs); 1.479 + if(blocked_data) { 1.480 + PORT_Memset((blocked_data->data + blocked_data->len 1.481 + - (int)pad_char), 1.482 + pad_char, (int)pad_char); 1.483 + } else { 1.484 + rv = SECFailure; 1.485 + goto loser; 1.486 + } 1.487 + } else { 1.488 + blocked_data = SECITEM_DupItem(src); 1.489 + if(blocked_data) { 1.490 + blocked_data->data = (unsigned char*)PORT_Realloc( 1.491 + blocked_data->data, 1.492 + blocked_data->len + bs); 1.493 + if(blocked_data->data) { 1.494 + blocked_data->len += bs; 1.495 + PORT_Memset((blocked_data->data + src->len), (char)bs, bs); 1.496 + } else { 1.497 + rv = SECFailure; 1.498 + goto loser; 1.499 + } 1.500 + } else { 1.501 + rv = SECFailure; 1.502 + goto loser; 1.503 + } 1.504 + } 1.505 + } else { 1.506 + blocked_data = SECITEM_DupItem(src); 1.507 + if(!blocked_data) { 1.508 + rv = SECFailure; 1.509 + goto loser; 1.510 + } 1.511 + } 1.512 + 1.513 + cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT, 1.514 + eKey, c_param); 1.515 + if(cx == NULL) { 1.516 + rv = SECFailure; 1.517 + goto loser; 1.518 + } 1.519 + 1.520 + rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len), 1.521 + (int)(src->len + 64), blocked_data->data, 1.522 + (int)blocked_data->len); 1.523 + PK11_DestroyContext((PK11Context*)cx, PR_TRUE); 1.524 + 1.525 +loser: 1.526 + /* let success fall through */ 1.527 + if(blocked_data != NULL) 1.528 + SECITEM_ZfreeItem(blocked_data, PR_TRUE); 1.529 + 1.530 + if(result != NULL) 1.531 + SECITEM_ZfreeItem(result, PR_TRUE); 1.532 + 1.533 + if(rv == SECFailure) 1.534 + PORT_ArenaRelease(poolp, mark); 1.535 + else 1.536 + PORT_ArenaUnmark(poolp, mark); 1.537 + 1.538 + if(eKey != NULL) 1.539 + PK11_FreeSymKey(eKey); 1.540 + 1.541 + if(slot != NULL) 1.542 + PK11_FreeSlot(slot); 1.543 + 1.544 + if(c_param != NULL) 1.545 + SECITEM_ZfreeItem(c_param, PR_TRUE); 1.546 + 1.547 + return rv; 1.548 +} 1.549 + 1.550 +/* the content of an encrypted data content info is decrypted. 1.551 + * it is assumed that for encrypted data, that the data has already 1.552 + * been set and is in the "encContent" field of the content info. 1.553 + * 1.554 + * cinfo is the content info to decrypt 1.555 + * 1.556 + * key is the key with which to perform the decryption. if the 1.557 + * algorithm is a password based encryption algorithm, the 1.558 + * key is actually a password which will be processed per 1.559 + * PKCS #5. 1.560 + * 1.561 + * in the event of an error, SECFailure is returned. SECSuccess 1.562 + * indicates a success. 1.563 + */ 1.564 +SECStatus 1.565 +SEC_PKCS7DecryptContents(PLArenaPool *poolp, 1.566 + SEC_PKCS7ContentInfo *cinfo, 1.567 + SECItem *key, 1.568 + void *wincx) 1.569 +{ 1.570 + SECAlgorithmID *algid = NULL; 1.571 + SECStatus rv = SECFailure; 1.572 + SECItem *result = NULL, *dest, *src; 1.573 + void *mark; 1.574 + 1.575 + PK11SymKey *eKey = NULL; 1.576 + PK11SlotInfo *slot = NULL; 1.577 + CK_MECHANISM_TYPE cryptoMechType; 1.578 + void *cx; 1.579 + SECItem *c_param = NULL; 1.580 + int bs; 1.581 + 1.582 + if((cinfo == NULL) || (key == NULL)) 1.583 + return SECFailure; 1.584 + 1.585 + if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA) 1.586 + return SECFailure; 1.587 + 1.588 + algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo); 1.589 + if(algid == NULL) 1.590 + return SECFailure; 1.591 + 1.592 + if(poolp == NULL) 1.593 + poolp = cinfo->poolp; 1.594 + 1.595 + mark = PORT_ArenaMark(poolp); 1.596 + 1.597 + src = &cinfo->content.encryptedData->encContentInfo.encContent; 1.598 + dest = &cinfo->content.encryptedData->encContentInfo.plainContent; 1.599 + dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64)); 1.600 + dest->len = (src->len + 64); 1.601 + if(dest->data == NULL) { 1.602 + rv = SECFailure; 1.603 + goto loser; 1.604 + } 1.605 + 1.606 + slot = PK11_GetInternalKeySlot(); 1.607 + if(slot == NULL) { 1.608 + rv = SECFailure; 1.609 + goto loser; 1.610 + } 1.611 + 1.612 + eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx); 1.613 + if(eKey == NULL) { 1.614 + rv = SECFailure; 1.615 + goto loser; 1.616 + } 1.617 + 1.618 + cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key); 1.619 + if (cryptoMechType == CKM_INVALID_MECHANISM) { 1.620 + rv = SECFailure; 1.621 + goto loser; 1.622 + } 1.623 + 1.624 + cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT, 1.625 + eKey, c_param); 1.626 + if(cx == NULL) { 1.627 + rv = SECFailure; 1.628 + goto loser; 1.629 + } 1.630 + 1.631 + rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len), 1.632 + (int)(src->len + 64), src->data, (int)src->len); 1.633 + PK11_DestroyContext((PK11Context *)cx, PR_TRUE); 1.634 + 1.635 + bs = PK11_GetBlockSize(cryptoMechType, c_param); 1.636 + if(bs) { 1.637 + /* check for proper badding in block algorithms. this assumes 1.638 + * RC2 cbc or a DES cbc variant. and the padding is thus defined 1.639 + */ 1.640 + if(((int)dest->data[dest->len-1] <= bs) && 1.641 + ((int)dest->data[dest->len-1] > 0)) { 1.642 + dest->len -= (int)dest->data[dest->len-1]; 1.643 + } else { 1.644 + rv = SECFailure; 1.645 + /* set an error ? */ 1.646 + } 1.647 + } 1.648 + 1.649 +loser: 1.650 + /* let success fall through */ 1.651 + if(result != NULL) 1.652 + SECITEM_ZfreeItem(result, PR_TRUE); 1.653 + 1.654 + if(rv == SECFailure) 1.655 + PORT_ArenaRelease(poolp, mark); 1.656 + else 1.657 + PORT_ArenaUnmark(poolp, mark); 1.658 + 1.659 + if(eKey != NULL) 1.660 + PK11_FreeSymKey(eKey); 1.661 + 1.662 + if(slot != NULL) 1.663 + PK11_FreeSlot(slot); 1.664 + 1.665 + if(c_param != NULL) 1.666 + SECITEM_ZfreeItem(c_param, PR_TRUE); 1.667 + 1.668 + return rv; 1.669 +} 1.670 + 1.671 +SECItem ** 1.672 +SEC_PKCS7GetCertificateList(SEC_PKCS7ContentInfo *cinfo) 1.673 +{ 1.674 + switch(SEC_PKCS7ContentType(cinfo)) 1.675 + { 1.676 + case SEC_OID_PKCS7_SIGNED_DATA: 1.677 + return cinfo->content.signedData->rawCerts; 1.678 + break; 1.679 + default: 1.680 + return NULL; 1.681 + break; 1.682 + } 1.683 +} 1.684 + 1.685 + 1.686 +int 1.687 +SEC_PKCS7GetKeyLength(SEC_PKCS7ContentInfo *cinfo) 1.688 +{ 1.689 + if (cinfo->contentTypeTag->offset == SEC_OID_PKCS7_ENVELOPED_DATA) 1.690 + return cinfo->content.envelopedData->encContentInfo.keysize; 1.691 + else 1.692 + return 0; 1.693 +} 1.694 +