1/*
2 * The contents of this file are subject to the Mozilla Public
3 * License Version 1.1 (the "License"); you may not use this file
4 * except in compliance with the License. You may obtain a copy of
5 * the License at http://www.mozilla.org/MPL/
6 *
7 * Software distributed under the License is distributed on an "AS
8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9 * implied. See the License for the specific language governing
10 * rights and limitations under the License.
11 *
12 * The Original Code is the Netscape security libraries.
13 *
14 * The Initial Developer of the Original Code is Netscape
15 * Communications Corporation.  Portions created by Netscape are
16 * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
17 * Rights Reserved.
18 *
19 * Contributor(s):
20 *
21 * Alternatively, the contents of this file may be used under the
22 * terms of the GNU General Public License Version 2 or later (the
23 * "GPL"), in which case the provisions of the GPL are applicable
24 * instead of those above.  If you wish to allow use of your
25 * version of this file only under the terms of the GPL and not to
26 * allow others to use your version of this file under the MPL,
27 * indicate your decision by deleting the provisions above and
28 * replace them with the notice and other provisions required by
29 * the GPL.  If you do not delete the provisions above, a recipient
30 * may use your version of this file under either the MPL or the
31 * GPL.
32 */
33
34/*
35 * Encryption/decryption routines for CMS implementation, none of which are exported.
36 *
37 */
38
39#include "cmslocal.h"
40
41#include "secoid.h"
42#include <security_asn1/secerr.h>
43#include <security_asn1/secasn1.h>
44#include <Security/SecAsn1Templates.h>
45#include <Security/cssmapi.h>
46#include <Security/cssmapple.h>
47#include <Security/SecKeyPriv.h>
48
49/*
50 * -------------------------------------------------------------------
51 * Cipher stuff.
52 */
53
54#if 0
55typedef OSStatus (*nss_cms_cipher_function) (void *, unsigned char *, unsigned int *,
56					unsigned int, const unsigned char *, unsigned int);
57typedef OSStatus (*nss_cms_cipher_destroy) (void *, Boolean);
58#endif
59
60#define BLOCK_SIZE 4096
61
62struct SecCmsCipherContextStr {
63#if 1
64    CSSM_CC_HANDLE	cc;			/* CSP CONTEXT */
65    Boolean		encrypt;		/* encrypt / decrypt switch */
66#else
67    void *		cx;			/* PK11 cipher context */
68    nss_cms_cipher_function doit;
69    nss_cms_cipher_destroy destroy;
70    Boolean		encrypt;		/* encrypt / decrypt switch */
71    int			block_size;		/* block & pad sizes for cipher */
72    int			pad_size;
73    int			pending_count;		/* pending data (not yet en/decrypted */
74    unsigned char	pending_buf[BLOCK_SIZE];/* because of blocking */
75#endif
76};
77
78typedef struct sec_rc2cbcParameterStr {
79    SECItem rc2ParameterVersion;
80    SECItem iv;
81} sec_rc2cbcParameter;
82
83static const SecAsn1Template sec_rc2cbc_parameter_template[] = {
84    { SEC_ASN1_SEQUENCE,
85          0, NULL, sizeof(sec_rc2cbcParameter) },
86    { SEC_ASN1_INTEGER | SEC_ASN1_SIGNED_INT,
87          offsetof(sec_rc2cbcParameter,rc2ParameterVersion) },
88    { SEC_ASN1_OCTET_STRING,
89          offsetof(sec_rc2cbcParameter,iv) },
90    { 0 }
91};
92
93/*
94** Convert a der encoded *signed* integer into a machine integral value.
95** If an underflow/overflow occurs, sets error code and returns min/max.
96*/
97static long
98DER_GetInteger(SECItem *it)
99{
100    long ival = 0;
101    CSSM_SIZE len = it->Length;
102    unsigned char *cp = it->Data;
103    unsigned long overflow = 0x1ffUL << (((sizeof(ival) - 1) * 8) - 1);
104    unsigned long ofloinit;
105
106    if (*cp & 0x80)
107        ival = -1L;
108    ofloinit = ival & overflow;
109
110    while (len) {
111        if ((ival & overflow) != ofloinit) {
112            PORT_SetError(SEC_ERROR_BAD_DER);
113            if (ival < 0) {
114                return LONG_MIN;
115            }
116            return LONG_MAX;
117        }
118        ival = ival << 8;
119        ival |= *cp++;
120        --len;
121    }
122    return ival;
123}
124
125/* S/MIME picked id values to represent differnt keysizes */
126/* I do have a formula, but it ain't pretty, and it only works because you
127 * can always match three points to a parabola:) */
128static unsigned char  rc2_map(SECItem *version)
129{
130    long x;
131
132    x = DER_GetInteger(version);
133
134    switch (x) {
135        case 58: return 128;
136        case 120: return 64;
137        case 160: return 40;
138    }
139    return 128;
140}
141
142static unsigned long  rc2_unmap(unsigned long x)
143{
144    switch (x) {
145        case 128: return 58;
146        case 64: return 120;
147        case 40: return 160;
148    }
149    return 58;
150}
151
152/* default IV size in bytes */
153#define DEFAULT_IV_SIZE	    8
154/* IV/block size for AES */
155#define AES_BLOCK_SIZE	    16
156/* max IV size in bytes */
157#define MAX_IV_SIZE	    AES_BLOCK_SIZE
158
159static SecCmsCipherContextRef
160SecCmsCipherContextStart(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid, Boolean encrypt)
161{
162    SecCmsCipherContextRef cc;
163    CSSM_CC_HANDLE ciphercc = 0;
164    SECOidData *oidData;
165    SECOidTag algtag;
166    CSSM_ALGORITHMS algorithm;
167    CSSM_PADDING padding = CSSM_PADDING_PKCS7;
168    CSSM_ENCRYPT_MODE mode;
169    CSSM_CSP_HANDLE cspHandle;
170    const CSSM_KEY *cssmKey;
171    OSStatus rv;
172    uint8 ivbuf[MAX_IV_SIZE];
173    CSSM_DATA initVector = { DEFAULT_IV_SIZE, ivbuf };
174    //CSSM_CONTEXT_ATTRIBUTE contextAttribute = { CSSM_ATTRIBUTE_ALG_PARAMS, sizeof(CSSM_DATA_PTR) };
175
176    rv = SecKeyGetCSPHandle(key, &cspHandle);
177    if (rv)
178	goto loser;
179    rv = SecKeyGetCSSMKey(key, &cssmKey);
180    if (rv)
181	goto loser;
182
183    // @@@ Add support for PBE based stuff
184
185    oidData = SECOID_FindOID(&algid->algorithm);
186    if (!oidData)
187	goto loser;
188    algtag = oidData->offset;
189    algorithm = oidData->cssmAlgorithm;
190    if (!algorithm)
191	goto loser;
192
193    switch (algtag)
194    {
195    case SEC_OID_RC2_CBC:
196    case SEC_OID_RC4:
197    case SEC_OID_DES_EDE3_CBC:
198    case SEC_OID_DES_EDE:
199    case SEC_OID_DES_CBC:
200    case SEC_OID_RC5_CBC_PAD:
201    case SEC_OID_FORTEZZA_SKIPJACK:
202	mode = CSSM_ALGMODE_CBCPadIV8;
203	break;
204
205    /* RFC 3565 says that these sizes refer to key size, NOT block size */
206    case SEC_OID_AES_128_CBC:
207    case SEC_OID_AES_192_CBC:
208    case SEC_OID_AES_256_CBC:
209	initVector.Length = AES_BLOCK_SIZE;
210	mode = CSSM_ALGMODE_CBCPadIV8;
211	break;
212
213    case SEC_OID_DES_ECB:
214    case SEC_OID_AES_128_ECB:
215    case SEC_OID_AES_192_ECB:
216    case SEC_OID_AES_256_ECB:
217	mode = CSSM_ALGMODE_ECBPad;
218	break;
219
220    case SEC_OID_DES_OFB:
221	mode = CSSM_ALGMODE_OFBPadIV8;
222	break;
223
224    case SEC_OID_DES_CFB:
225	mode = CSSM_ALGMODE_CFBPadIV8;
226	break;
227
228    default:
229	goto loser;
230    }
231
232    if (encrypt)
233    {
234	CSSM_CC_HANDLE randomcc;
235	//SECItem *parameters;
236
237	// Generate random initVector
238	if (CSSM_CSP_CreateRandomGenContext(cspHandle,
239		CSSM_ALGID_APPLE_YARROW,
240		NULL, /* seed*/
241		initVector.Length,
242		&randomcc))
243	    goto loser;
244
245	if (CSSM_GenerateRandom(randomcc, &initVector))
246	    goto loser;
247	CSSM_DeleteContext(randomcc);
248
249	// Put IV into algid.parameters
250	switch (algtag)
251	{
252	case SEC_OID_RC4:
253	case SEC_OID_DES_EDE3_CBC:
254	case SEC_OID_DES_EDE:
255	case SEC_OID_DES_CBC:
256	case SEC_OID_AES_128_CBC:
257	case SEC_OID_AES_192_CBC:
258	case SEC_OID_AES_256_CBC:
259	case SEC_OID_FORTEZZA_SKIPJACK:
260	case SEC_OID_DES_ECB:
261	case SEC_OID_AES_128_ECB:
262	case SEC_OID_AES_192_ECB:
263	case SEC_OID_AES_256_ECB:
264	case SEC_OID_DES_OFB:
265	case SEC_OID_DES_CFB:
266	    /* Just encode the initVector as an octet string. */
267	    if (!SEC_ASN1EncodeItem(poolp, &algid->parameters,
268				    &initVector, kSecAsn1OctetStringTemplate))
269		goto loser;
270	    break;
271
272	case SEC_OID_RC2_CBC:
273	{
274	    sec_rc2cbcParameter rc2 = {};
275	    unsigned long rc2version;
276	    SECItem *newParams;
277
278	    rc2.iv = initVector;
279	    rc2version = rc2_unmap(cssmKey->KeyHeader.LogicalKeySizeInBits);
280	    if (!SEC_ASN1EncodeUnsignedInteger (NULL, &(rc2.rc2ParameterVersion),
281					       rc2version))
282		goto loser;
283	    newParams = SEC_ASN1EncodeItem (poolp, &algid->parameters, &rc2,
284				sec_rc2cbc_parameter_template);
285	    PORT_Free(rc2.rc2ParameterVersion.Data);
286	    if (newParams == NULL)
287		goto loser;
288	    break;
289	}
290	case SEC_OID_RC5_CBC_PAD:
291	default:
292	    // @@@ Implement rc5 params stuff.
293	    goto loser;
294	    break;
295	}
296    }
297    else
298    {
299	// Extract IV from algid.parameters
300	// Put IV into algid.parameters
301	switch (algtag)
302	{
303	case SEC_OID_RC4:
304	case SEC_OID_DES_EDE3_CBC:
305	case SEC_OID_DES_EDE:
306	case SEC_OID_DES_CBC:
307	case SEC_OID_AES_128_CBC:
308	case SEC_OID_AES_192_CBC:
309	case SEC_OID_AES_256_CBC:
310	case SEC_OID_FORTEZZA_SKIPJACK:
311	case SEC_OID_DES_ECB:
312	case SEC_OID_AES_128_ECB:
313	case SEC_OID_AES_192_ECB:
314	case SEC_OID_AES_256_ECB:
315	case SEC_OID_DES_OFB:
316	case SEC_OID_DES_CFB:
317	{
318	    CSSM_DATA iv = {};
319	    /* Just decode the initVector from an octet string. */
320	    rv = SEC_ASN1DecodeItem(NULL, &iv, kSecAsn1OctetStringTemplate, &(algid->parameters));
321	    if (rv)
322		goto loser;
323	    if (initVector.Length != iv.Length) {
324		PORT_Free(iv.Data);
325		goto loser;
326	    }
327	    memcpy(initVector.Data, iv.Data, initVector.Length);
328	    PORT_Free(iv.Data);
329	    break;
330	}
331	case SEC_OID_RC2_CBC:
332	{
333	    sec_rc2cbcParameter rc2 = {};
334	    unsigned long ulEffectiveBits;
335
336	    rv = SEC_ASN1DecodeItem(NULL, &rc2 ,sec_rc2cbc_parameter_template,
337							    &(algid->parameters));
338	    if (rv)
339		goto loser;
340
341	    if (initVector.Length != rc2.iv.Length) {
342		PORT_Free(rc2.iv.Data);
343		PORT_Free(rc2.rc2ParameterVersion.Data);
344		goto loser;
345	    }
346	    memcpy(initVector.Data, rc2.iv.Data, initVector.Length);
347	    PORT_Free(rc2.iv.Data);
348
349	    ulEffectiveBits = rc2_map(&rc2.rc2ParameterVersion);
350	    PORT_Free(rc2.rc2ParameterVersion.Data);
351	    if (ulEffectiveBits != cssmKey->KeyHeader.LogicalKeySizeInBits)
352		goto loser;
353	    break;
354	}
355	case SEC_OID_RC5_CBC_PAD:
356	default:
357	    // @@@ Implement rc5 params stuff.
358	    goto loser;
359	    break;
360	}
361    }
362
363    if (CSSM_CSP_CreateSymmetricContext(cspHandle,
364	    algorithm,
365	    mode,
366	    NULL, /* accessCred */
367	    cssmKey,
368	    &initVector,
369	    padding,
370	    NULL, /* reserved */
371	    &ciphercc))
372	goto loser;
373
374    if (encrypt)
375	rv = CSSM_EncryptDataInit(ciphercc);
376    else
377	rv = CSSM_DecryptDataInit(ciphercc);
378    if (rv)
379	goto loser;
380
381    cc = (SecCmsCipherContextRef)PORT_ZAlloc(sizeof(SecCmsCipherContext));
382    if (cc == NULL)
383	goto loser;
384
385    cc->cc = ciphercc;
386    cc->encrypt = encrypt;
387
388    return cc;
389loser:
390    if (ciphercc)
391	CSSM_DeleteContext(ciphercc);
392
393    return NULL;
394}
395
396/*
397 * SecCmsCipherContextStartDecrypt - create a cipher context to do decryption
398 * based on the given bulk * encryption key and algorithm identifier (which may include an iv).
399 *
400 * XXX Once both are working, it might be nice to combine this and the
401 * function below (for starting up encryption) into one routine, and just
402 * have two simple cover functions which call it.
403 */
404SecCmsCipherContextRef
405SecCmsCipherContextStartDecrypt(SecSymmetricKeyRef key, SECAlgorithmID *algid)
406{
407    return SecCmsCipherContextStart(NULL, key, algid, PR_FALSE);
408#if 0
409    SecCmsCipherContextRef cc;
410    void *ciphercx;
411    CK_MECHANISM_TYPE mechanism;
412    CSSM_DATA_PTR param;
413    PK11SlotInfo *slot;
414    SECOidTag algtag;
415
416    algtag = SECOID_GetAlgorithmTag(algid);
417
418    /* set param and mechanism */
419    if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
420	CK_MECHANISM pbeMech, cryptoMech;
421	CSSM_DATA_PTR pbeParams;
422	SEC_PKCS5KeyAndPassword *keyPwd;
423
424	PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM));
425	PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM));
426
427	/* HACK ALERT!
428	 * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword *
429	 */
430	keyPwd = (SEC_PKCS5KeyAndPassword *)key;
431	key = keyPwd->key;
432
433	/* find correct PK11 mechanism and parameters to initialize pbeMech */
434	pbeMech.mechanism = PK11_AlgtagToMechanism(algtag);
435	pbeParams = PK11_ParamFromAlgid(algid);
436	if (!pbeParams)
437	    return NULL;
438	pbeMech.pParameter = pbeParams->Data;
439	pbeMech.ulParameterLen = pbeParams->Length;
440
441	/* now map pbeMech to cryptoMech */
442	if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem,
443						  PR_FALSE) != CKR_OK) {
444	    SECITEM_ZfreeItem(pbeParams, PR_TRUE);
445	    return NULL;
446	}
447	SECITEM_ZfreeItem(pbeParams, PR_TRUE);
448
449	/* and use it to initialize param & mechanism */
450	if ((param = (CSSM_DATA_PTR)PORT_ZAlloc(sizeof(CSSM_DATA))) == NULL)
451	     return NULL;
452
453	param->Data = (unsigned char *)cryptoMech.pParameter;
454	param->Length = cryptoMech.ulParameterLen;
455	mechanism = cryptoMech.mechanism;
456    } else {
457	mechanism = PK11_AlgtagToMechanism(algtag);
458	if ((param = PK11_ParamFromAlgid(algid)) == NULL)
459	    return NULL;
460    }
461
462    cc = (SecCmsCipherContextRef)PORT_ZAlloc(sizeof(SecCmsCipherContext));
463    if (cc == NULL) {
464	SECITEM_FreeItem(param,PR_TRUE);
465	return NULL;
466    }
467
468    /* figure out pad and block sizes */
469    cc->pad_size = PK11_GetBlockSize(mechanism, param);
470    slot = PK11_GetSlotFromKey(key);
471    cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size;
472    PK11_FreeSlot(slot);
473
474    /* create PK11 cipher context */
475    ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_DECRYPT, key, param);
476    SECITEM_FreeItem(param, PR_TRUE);
477    if (ciphercx == NULL) {
478	PORT_Free (cc);
479	return NULL;
480    }
481
482    cc->cx = ciphercx;
483    cc->doit =  (nss_cms_cipher_function) PK11_CipherOp;
484    cc->destroy = (nss_cms_cipher_destroy) PK11_DestroyContext;
485    cc->encrypt = PR_FALSE;
486    cc->pending_count = 0;
487
488    return cc;
489#endif
490}
491
492/*
493 * SecCmsCipherContextStartEncrypt - create a cipher object to do encryption,
494 * based on the given bulk encryption key and algorithm tag.  Fill in the algorithm
495 * identifier (which may include an iv) appropriately.
496 *
497 * XXX Once both are working, it might be nice to combine this and the
498 * function above (for starting up decryption) into one routine, and just
499 * have two simple cover functions which call it.
500 */
501SecCmsCipherContextRef
502SecCmsCipherContextStartEncrypt(PRArenaPool *poolp, SecSymmetricKeyRef key, SECAlgorithmID *algid)
503{
504    return SecCmsCipherContextStart(poolp, key, algid, PR_TRUE);
505#if 0
506    SecCmsCipherContextRef cc;
507    void *ciphercx;
508    CSSM_DATA_PTR param;
509    OSStatus rv;
510    CK_MECHANISM_TYPE mechanism;
511    PK11SlotInfo *slot;
512    Boolean needToEncodeAlgid = PR_FALSE;
513    SECOidTag algtag = SECOID_GetAlgorithmTag(algid);
514
515    /* set param and mechanism */
516    if (SEC_PKCS5IsAlgorithmPBEAlg(algid)) {
517	CK_MECHANISM pbeMech, cryptoMech;
518	CSSM_DATA_PTR pbeParams;
519	SEC_PKCS5KeyAndPassword *keyPwd;
520
521	PORT_Memset(&pbeMech, 0, sizeof(CK_MECHANISM));
522	PORT_Memset(&cryptoMech, 0, sizeof(CK_MECHANISM));
523
524	/* HACK ALERT!
525	 * in this case, key is not actually a SecSymmetricKeyRef, but a SEC_PKCS5KeyAndPassword *
526	 */
527	keyPwd = (SEC_PKCS5KeyAndPassword *)key;
528	key = keyPwd->key;
529
530	/* find correct PK11 mechanism and parameters to initialize pbeMech */
531	pbeMech.mechanism = PK11_AlgtagToMechanism(algtag);
532	pbeParams = PK11_ParamFromAlgid(algid);
533	if (!pbeParams)
534	    return NULL;
535	pbeMech.pParameter = pbeParams->Data;
536	pbeMech.ulParameterLen = pbeParams->Length;
537
538	/* now map pbeMech to cryptoMech */
539	if (PK11_MapPBEMechanismToCryptoMechanism(&pbeMech, &cryptoMech, keyPwd->pwitem,
540						  PR_FALSE) != CKR_OK) {
541	    SECITEM_ZfreeItem(pbeParams, PR_TRUE);
542	    return NULL;
543	}
544	SECITEM_ZfreeItem(pbeParams, PR_TRUE);
545
546	/* and use it to initialize param & mechanism */
547	if ((param = (CSSM_DATA_PTR)PORT_ZAlloc(sizeof(CSSM_DATA))) == NULL)
548	    return NULL;
549
550	param->Data = (unsigned char *)cryptoMech.pParameter;
551	param->Length = cryptoMech.ulParameterLen;
552	mechanism = cryptoMech.mechanism;
553    } else {
554	mechanism = PK11_AlgtagToMechanism(algtag);
555	if ((param = PK11_GenerateNewParam(mechanism, key)) == NULL)
556	    return NULL;
557	needToEncodeAlgid = PR_TRUE;
558    }
559
560    cc = (SecCmsCipherContextRef)PORT_ZAlloc(sizeof(SecCmsCipherContext));
561    if (cc == NULL)
562	return NULL;
563
564    /* now find pad and block sizes for our mechanism */
565    cc->pad_size = PK11_GetBlockSize(mechanism,param);
566    slot = PK11_GetSlotFromKey(key);
567    cc->block_size = PK11_IsHW(slot) ? BLOCK_SIZE : cc->pad_size;
568    PK11_FreeSlot(slot);
569
570    /* and here we go, creating a PK11 cipher context */
571    ciphercx = PK11_CreateContextBySymKey(mechanism, CKA_ENCRYPT, key, param);
572    if (ciphercx == NULL) {
573	PORT_Free(cc);
574	cc = NULL;
575	goto loser;
576    }
577
578    /*
579     * These are placed after the CreateContextBySymKey() because some
580     * mechanisms have to generate their IVs from their card (i.e. FORTEZZA).
581     * Don't move it from here.
582     * XXX is that right? the purpose of this is to get the correct algid
583     *     containing the IVs etc. for encoding. this means we need to set this up
584     *     BEFORE encoding the algid in the contentInfo, right?
585     */
586    if (needToEncodeAlgid) {
587	rv = PK11_ParamToAlgid(algtag, param, poolp, algid);
588	if(rv != SECSuccess) {
589	    PORT_Free(cc);
590	    cc = NULL;
591	    goto loser;
592	}
593    }
594
595    cc->cx = ciphercx;
596    cc->doit = (nss_cms_cipher_function)PK11_CipherOp;
597    cc->destroy = (nss_cms_cipher_destroy)PK11_DestroyContext;
598    cc->encrypt = PR_TRUE;
599    cc->pending_count = 0;
600
601loser:
602    SECITEM_FreeItem(param, PR_TRUE);
603
604    return cc;
605#endif
606}
607
608void
609SecCmsCipherContextDestroy(SecCmsCipherContextRef cc)
610{
611    PORT_Assert(cc != NULL);
612    if (cc == NULL)
613	return;
614    CSSM_DeleteContext(cc->cc);
615    PORT_Free(cc);
616}
617
618static unsigned int
619SecCmsCipherContextLength(SecCmsCipherContextRef cc, unsigned int input_len, Boolean final, Boolean encrypt)
620{
621    CSSM_QUERY_SIZE_DATA dataBlockSize[2] = { { input_len, 0 }, { input_len, 0 } };
622    /* Hack CDSA treats the last block as the final one.  So unless we are being asked to report the final size we ask for 2 block and ignore the second (final) one. */
623    OSStatus rv = CSSM_QuerySize(cc->cc, cc->encrypt, final ? 1 : 2, dataBlockSize);
624    if (rv)
625    {
626	PORT_SetError(rv);
627	return 0;
628    }
629
630    return dataBlockSize[0].SizeOutputBlock;
631}
632
633/*
634 * SecCmsCipherContextDecryptLength - find the output length of the next call to decrypt.
635 *
636 * cc - the cipher context
637 * input_len - number of bytes used as input
638 * final - true if this is the final chunk of data
639 *
640 * Result can be used to perform memory allocations.  Note that the amount
641 * is exactly accurate only when not doing a block cipher or when final
642 * is false, otherwise it is an upper bound on the amount because until
643 * we see the data we do not know how many padding bytes there are
644 * (always between 1 and bsize).
645 *
646 * Note that this can return zero, which does not mean that the decrypt
647 * operation can be skipped!  (It simply means that there are not enough
648 * bytes to make up an entire block; the bytes will be reserved until
649 * there are enough to encrypt/decrypt at least one block.)  However,
650 * if zero is returned it *does* mean that no output buffer need be
651 * passed in to the subsequent decrypt operation, as no output bytes
652 * will be stored.
653 */
654size_t
655SecCmsCipherContextDecryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final)
656{
657#if 1
658    return SecCmsCipherContextLength(cc, (unsigned int)input_len, final, PR_FALSE);
659#else
660    int blocks, block_size;
661
662    PORT_Assert (! cc->encrypt);
663
664    block_size = cc->block_size;
665
666    /*
667     * If this is not a block cipher, then we always have the same
668     * number of output bytes as we had input bytes.
669     */
670    if (block_size == 0)
671	return input_len;
672
673    /*
674     * On the final call, we will always use up all of the pending
675     * bytes plus all of the input bytes, *but*, there will be padding
676     * at the end and we cannot predict how many bytes of padding we
677     * will end up removing.  The amount given here is actually known
678     * to be at least 1 byte too long (because we know we will have
679     * at least 1 byte of padding), but seemed clearer/better to me.
680     */
681    if (final)
682	return cc->pending_count + input_len;
683
684    /*
685     * Okay, this amount is exactly what we will output on the
686     * next cipher operation.  We will always hang onto the last
687     * 1 - block_size bytes for non-final operations.  That is,
688     * we will do as many complete blocks as we can *except* the
689     * last block (complete or partial).  (This is because until
690     * we know we are at the end, we cannot know when to interpret
691     * and removing the padding byte(s), which are guaranteed to
692     * be there.)
693     */
694    blocks = (cc->pending_count + input_len - 1) / block_size;
695    return blocks * block_size;
696#endif
697}
698
699/*
700 * SecCmsCipherContextEncryptLength - find the output length of the next call to encrypt.
701 *
702 * cc - the cipher context
703 * input_len - number of bytes used as input
704 * final - true if this is the final chunk of data
705 *
706 * Result can be used to perform memory allocations.
707 *
708 * Note that this can return zero, which does not mean that the encrypt
709 * operation can be skipped!  (It simply means that there are not enough
710 * bytes to make up an entire block; the bytes will be reserved until
711 * there are enough to encrypt/decrypt at least one block.)  However,
712 * if zero is returned it *does* mean that no output buffer need be
713 * passed in to the subsequent encrypt operation, as no output bytes
714 * will be stored.
715 */
716size_t
717SecCmsCipherContextEncryptLength(SecCmsCipherContextRef cc, size_t input_len, Boolean final)
718{
719#if 1
720    return SecCmsCipherContextLength(cc, (unsigned int)input_len, final, PR_TRUE);
721#else
722    int blocks, block_size;
723    int pad_size;
724
725    PORT_Assert (cc->encrypt);
726
727    block_size = cc->block_size;
728    pad_size = cc->pad_size;
729
730    /*
731     * If this is not a block cipher, then we always have the same
732     * number of output bytes as we had input bytes.
733     */
734    if (block_size == 0)
735	return input_len;
736
737    /*
738     * On the final call, we only send out what we need for
739     * remaining bytes plus the padding.  (There is always padding,
740     * so even if we have an exact number of blocks as input, we
741     * will add another full block that is just padding.)
742     */
743    if (final) {
744	if (pad_size == 0) {
745    	    return cc->pending_count + input_len;
746	} else {
747    	    blocks = (cc->pending_count + input_len) / pad_size;
748	    blocks++;
749	    return blocks*pad_size;
750	}
751    }
752
753    /*
754     * Now, count the number of complete blocks of data we have.
755     */
756    blocks = (cc->pending_count + input_len) / block_size;
757
758
759    return blocks * block_size;
760#endif
761}
762
763
764static OSStatus
765SecCmsCipherContextCrypt(SecCmsCipherContextRef cc, unsigned char *output,
766		  size_t *output_len_p, size_t max_output_len,
767		  const unsigned char *input, size_t input_len,
768		  Boolean final, Boolean encrypt)
769{
770    CSSM_DATA outputBuf = { max_output_len, output };
771    CSSM_SIZE bytes_output = 0;
772    OSStatus rv = 0;
773
774    if (input_len)
775    {
776	CSSM_DATA inputBuf = { input_len, (uint8 *)input };
777
778	if (encrypt)
779	    rv = CSSM_EncryptDataUpdate(cc->cc, &inputBuf, 1, &outputBuf, 1, &bytes_output);
780	else
781	    rv = CSSM_DecryptDataUpdate(cc->cc, &inputBuf, 1, &outputBuf, 1, &bytes_output);
782    }
783
784    if (!rv && final)
785    {
786	CSSM_DATA remainderBuf = { max_output_len - bytes_output, output + bytes_output };
787	if (encrypt)
788	    rv = CSSM_EncryptDataFinal(cc->cc, &remainderBuf);
789	else
790	    rv = CSSM_DecryptDataFinal(cc->cc, &remainderBuf);
791
792	bytes_output += remainderBuf.Length;
793    }
794
795    if (rv)
796	PORT_SetError(SEC_ERROR_BAD_DATA);
797    else if (output_len_p)
798	*output_len_p = bytes_output;
799
800    return rv;
801}
802
803/*
804 * SecCmsCipherContextDecrypt - do the decryption
805 *
806 * cc - the cipher context
807 * output - buffer for decrypted result bytes
808 * output_len_p - number of bytes in output
809 * max_output_len - upper bound on bytes to put into output
810 * input - pointer to input bytes
811 * input_len - number of input bytes
812 * final - true if this is the final chunk of data
813 *
814 * Decrypts a given length of input buffer (starting at "input" and
815 * containing "input_len" bytes), placing the decrypted bytes in
816 * "output" and storing the output length in "*output_len_p".
817 * "cc" is the return value from SecCmsCipherStartDecrypt.
818 * When "final" is true, this is the last of the data to be decrypted.
819 *
820 * This is much more complicated than it sounds when the cipher is
821 * a block-type, meaning that the decryption function will only
822 * operate on whole blocks.  But our caller is operating stream-wise,
823 * and can pass in any number of bytes.  So we need to keep track
824 * of block boundaries.  We save excess bytes between calls in "cc".
825 * We also need to determine which bytes are padding, and remove
826 * them from the output.  We can only do this step when we know we
827 * have the final block of data.  PKCS #7 specifies that the padding
828 * used for a block cipher is a string of bytes, each of whose value is
829 * the same as the length of the padding, and that all data is padded.
830 * (Even data that starts out with an exact multiple of blocks gets
831 * added to it another block, all of which is padding.)
832 */
833OSStatus
834SecCmsCipherContextDecrypt(SecCmsCipherContextRef cc, unsigned char *output,
835		  size_t *output_len_p, size_t max_output_len,
836		  const unsigned char *input, size_t input_len,
837		  Boolean final)
838{
839#if 1
840    return SecCmsCipherContextCrypt(cc, output,
841		  output_len_p,  max_output_len,
842		  input, input_len,
843		  final, PR_FALSE);
844#else
845    int blocks, bsize, pcount, padsize;
846    unsigned int max_needed, ifraglen, ofraglen, output_len;
847    unsigned char *pbuf;
848    OSStatus rv;
849
850    PORT_Assert (! cc->encrypt);
851
852    /*
853     * Check that we have enough room for the output.  Our caller should
854     * already handle this; failure is really an internal error (i.e. bug).
855     */
856    max_needed = SecCmsCipherContextDecryptLength(cc, input_len, final);
857    PORT_Assert (max_output_len >= max_needed);
858    if (max_output_len < max_needed) {
859	/* PORT_SetError (XXX); */
860	return SECFailure;
861    }
862
863    /*
864     * hardware encryption does not like small decryption sizes here, so we
865     * allow both blocking and padding.
866     */
867    bsize = cc->block_size;
868    padsize = cc->pad_size;
869
870    /*
871     * When no blocking or padding work to do, we can simply call the
872     * cipher function and we are done.
873     */
874    if (bsize == 0) {
875	return (* cc->doit) (cc->cx, output, output_len_p, max_output_len,
876			      input, input_len);
877    }
878
879    pcount = cc->pending_count;
880    pbuf = cc->pending_buf;
881
882    output_len = 0;
883
884    if (pcount) {
885	/*
886	 * Try to fill in an entire block, starting with the bytes
887	 * we already have saved away.
888	 */
889	while (input_len && pcount < bsize) {
890	    pbuf[pcount++] = *input++;
891	    input_len--;
892	}
893	/*
894	 * If we have at most a whole block and this is not our last call,
895	 * then we are done for now.  (We do not try to decrypt a lone
896	 * single block because we cannot interpret the padding bytes
897	 * until we know we are handling the very last block of all input.)
898	 */
899	if (input_len == 0 && !final) {
900	    cc->pending_count = pcount;
901	    if (output_len_p)
902		*output_len_p = 0;
903	    return SECSuccess;
904	}
905	/*
906	 * Given the logic above, we expect to have a full block by now.
907	 * If we do not, there is something wrong, either with our own
908	 * logic or with (length of) the data given to us.
909	 */
910	if ((padsize != 0) && (pcount % padsize) != 0) {
911	    PORT_Assert (final);
912	    PORT_SetError (SEC_ERROR_BAD_DATA);
913	    return SECFailure;
914	}
915	/*
916	 * Decrypt the block.
917	 */
918	rv = (*cc->doit)(cc->cx, output, &ofraglen, max_output_len,
919			    pbuf, pcount);
920	if (rv != SECSuccess)
921	    return rv;
922
923	/*
924	 * For now anyway, all of our ciphers have the same number of
925	 * bytes of output as they do input.  If this ever becomes untrue,
926	 * then SecCmsCipherContextDecryptLength needs to be made smarter!
927	 */
928	PORT_Assert(ofraglen == pcount);
929
930	/*
931	 * Account for the bytes now in output.
932	 */
933	max_output_len -= ofraglen;
934	output_len += ofraglen;
935	output += ofraglen;
936    }
937
938    /*
939     * If this is our last call, we expect to have an exact number of
940     * blocks left to be decrypted; we will decrypt them all.
941     *
942     * If not our last call, we always save between 1 and bsize bytes
943     * until next time.  (We must do this because we cannot be sure
944     * that none of the decrypted bytes are padding bytes until we
945     * have at least another whole block of data.  You cannot tell by
946     * looking -- the data could be anything -- you can only tell by
947     * context, knowing you are looking at the last block.)  We could
948     * decrypt a whole block now but it is easier if we just treat it
949     * the same way we treat partial block bytes.
950     */
951    if (final) {
952	if (padsize) {
953	    blocks = input_len / padsize;
954	    ifraglen = blocks * padsize;
955	} else ifraglen = input_len;
956	PORT_Assert (ifraglen == input_len);
957
958	if (ifraglen != input_len) {
959	    PORT_SetError(SEC_ERROR_BAD_DATA);
960	    return SECFailure;
961	}
962    } else {
963	blocks = (input_len - 1) / bsize;
964	ifraglen = blocks * bsize;
965	PORT_Assert (ifraglen < input_len);
966
967	pcount = input_len - ifraglen;
968	PORT_Memcpy (pbuf, input + ifraglen, pcount);
969	cc->pending_count = pcount;
970    }
971
972    if (ifraglen) {
973	rv = (* cc->doit)(cc->cx, output, &ofraglen, max_output_len,
974			    input, ifraglen);
975	if (rv != SECSuccess)
976	    return rv;
977
978	/*
979	 * For now anyway, all of our ciphers have the same number of
980	 * bytes of output as they do input.  If this ever becomes untrue,
981	 * then sec_PKCS7DecryptLength needs to be made smarter!
982	 */
983	PORT_Assert (ifraglen == ofraglen);
984	if (ifraglen != ofraglen) {
985	    PORT_SetError(SEC_ERROR_BAD_DATA);
986	    return SECFailure;
987	}
988
989	output_len += ofraglen;
990    } else {
991	ofraglen = 0;
992    }
993
994    /*
995     * If we just did our very last block, "remove" the padding by
996     * adjusting the output length.
997     */
998    if (final && (padsize != 0)) {
999	unsigned int padlen = *(output + ofraglen - 1);
1000
1001	if (padlen == 0 || padlen > padsize) {
1002	    PORT_SetError(SEC_ERROR_BAD_DATA);
1003	    return SECFailure;
1004	}
1005	output_len -= padlen;
1006    }
1007
1008    PORT_Assert (output_len_p != NULL || output_len == 0);
1009    if (output_len_p != NULL)
1010	*output_len_p = output_len;
1011
1012    return SECSuccess;
1013#endif
1014}
1015
1016/*
1017 * SecCmsCipherContextEncrypt - do the encryption
1018 *
1019 * cc - the cipher context
1020 * output - buffer for decrypted result bytes
1021 * output_len_p - number of bytes in output
1022 * max_output_len - upper bound on bytes to put into output
1023 * input - pointer to input bytes
1024 * input_len - number of input bytes
1025 * final - true if this is the final chunk of data
1026 *
1027 * Encrypts a given length of input buffer (starting at "input" and
1028 * containing "input_len" bytes), placing the encrypted bytes in
1029 * "output" and storing the output length in "*output_len_p".
1030 * "cc" is the return value from SecCmsCipherStartEncrypt.
1031 * When "final" is true, this is the last of the data to be encrypted.
1032 *
1033 * This is much more complicated than it sounds when the cipher is
1034 * a block-type, meaning that the encryption function will only
1035 * operate on whole blocks.  But our caller is operating stream-wise,
1036 * and can pass in any number of bytes.  So we need to keep track
1037 * of block boundaries.  We save excess bytes between calls in "cc".
1038 * We also need to add padding bytes at the end.  PKCS #7 specifies
1039 * that the padding used for a block cipher is a string of bytes,
1040 * each of whose value is the same as the length of the padding,
1041 * and that all data is padded.  (Even data that starts out with
1042 * an exact multiple of blocks gets added to it another block,
1043 * all of which is padding.)
1044 *
1045 * XXX I would kind of like to combine this with the function above
1046 * which does decryption, since they have a lot in common.  But the
1047 * tricky parts about padding and filling blocks would be much
1048 * harder to read that way, so I left them separate.  At least for
1049 * now until it is clear that they are right.
1050 */
1051OSStatus
1052SecCmsCipherContextEncrypt(SecCmsCipherContextRef cc, unsigned char *output,
1053		  size_t *output_len_p, size_t max_output_len,
1054		  const unsigned char *input, size_t input_len,
1055		  Boolean final)
1056{
1057#if 1
1058    return SecCmsCipherContextCrypt(cc, output,
1059		  output_len_p,  max_output_len,
1060		  input, input_len,
1061		  final, PR_TRUE);
1062#else
1063    int blocks, bsize, padlen, pcount, padsize;
1064    unsigned int max_needed, ifraglen, ofraglen, output_len;
1065    unsigned char *pbuf;
1066    OSStatus rv;
1067
1068    PORT_Assert (cc->encrypt);
1069
1070    /*
1071     * Check that we have enough room for the output.  Our caller should
1072     * already handle this; failure is really an internal error (i.e. bug).
1073     */
1074    max_needed = SecCmsCipherContextEncryptLength (cc, input_len, final);
1075    PORT_Assert (max_output_len >= max_needed);
1076    if (max_output_len < max_needed) {
1077	/* PORT_SetError (XXX); */
1078	return SECFailure;
1079    }
1080
1081    bsize = cc->block_size;
1082    padsize = cc->pad_size;
1083
1084    /*
1085     * When no blocking and padding work to do, we can simply call the
1086     * cipher function and we are done.
1087     */
1088    if (bsize == 0) {
1089	return (*cc->doit)(cc->cx, output, output_len_p, max_output_len,
1090			      input, input_len);
1091    }
1092
1093    pcount = cc->pending_count;
1094    pbuf = cc->pending_buf;
1095
1096    output_len = 0;
1097
1098    if (pcount) {
1099	/*
1100	 * Try to fill in an entire block, starting with the bytes
1101	 * we already have saved away.
1102	 */
1103	while (input_len && pcount < bsize) {
1104	    pbuf[pcount++] = *input++;
1105	    input_len--;
1106	}
1107	/*
1108	 * If we do not have a full block and we know we will be
1109	 * called again, then we are done for now.
1110	 */
1111	if (pcount < bsize && !final) {
1112	    cc->pending_count = pcount;
1113	    if (output_len_p != NULL)
1114		*output_len_p = 0;
1115	    return SECSuccess;
1116	}
1117	/*
1118	 * If we have a whole block available, encrypt it.
1119	 */
1120	if ((padsize == 0) || (pcount % padsize) == 0) {
1121	    rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
1122				pbuf, pcount);
1123	    if (rv != SECSuccess)
1124		return rv;
1125
1126	    /*
1127	     * For now anyway, all of our ciphers have the same number of
1128	     * bytes of output as they do input.  If this ever becomes untrue,
1129	     * then sec_PKCS7EncryptLength needs to be made smarter!
1130	     */
1131	    PORT_Assert (ofraglen == pcount);
1132
1133	    /*
1134	     * Account for the bytes now in output.
1135	     */
1136	    max_output_len -= ofraglen;
1137	    output_len += ofraglen;
1138	    output += ofraglen;
1139
1140	    pcount = 0;
1141	}
1142    }
1143
1144    if (input_len) {
1145	PORT_Assert (pcount == 0);
1146
1147	blocks = input_len / bsize;
1148	ifraglen = blocks * bsize;
1149
1150	if (ifraglen) {
1151	    rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
1152				input, ifraglen);
1153	    if (rv != SECSuccess)
1154		return rv;
1155
1156	    /*
1157	     * For now anyway, all of our ciphers have the same number of
1158	     * bytes of output as they do input.  If this ever becomes untrue,
1159	     * then sec_PKCS7EncryptLength needs to be made smarter!
1160	     */
1161	    PORT_Assert (ifraglen == ofraglen);
1162
1163	    max_output_len -= ofraglen;
1164	    output_len += ofraglen;
1165	    output += ofraglen;
1166	}
1167
1168	pcount = input_len - ifraglen;
1169	PORT_Assert (pcount < bsize);
1170	if (pcount)
1171	    PORT_Memcpy (pbuf, input + ifraglen, pcount);
1172    }
1173
1174    if (final) {
1175	padlen = padsize - (pcount % padsize);
1176	PORT_Memset (pbuf + pcount, padlen, padlen);
1177	rv = (* cc->doit) (cc->cx, output, &ofraglen, max_output_len,
1178			    pbuf, pcount+padlen);
1179	if (rv != SECSuccess)
1180	    return rv;
1181
1182	/*
1183	 * For now anyway, all of our ciphers have the same number of
1184	 * bytes of output as they do input.  If this ever becomes untrue,
1185	 * then sec_PKCS7EncryptLength needs to be made smarter!
1186	 */
1187	PORT_Assert (ofraglen == (pcount+padlen));
1188	output_len += ofraglen;
1189    } else {
1190	cc->pending_count = pcount;
1191    }
1192
1193    PORT_Assert (output_len_p != NULL || output_len == 0);
1194    if (output_len_p != NULL)
1195	*output_len_p = output_len;
1196
1197    return SECSuccess;
1198#endif
1199}
1200