Example #1
0
static void transformAES_CBC(CCOperation operation, const CryptoAlgorithmAesCbcParams& parameters, const CryptoKeyAES& key, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise)
{
    static_assert(sizeof(parameters.iv) == kCCBlockSizeAES128, "Initialization vector size must be the same as algorithm block size");

    size_t keyLengthInBytes = key.key().size();
    if (keyLengthInBytes != 16 && keyLengthInBytes != 24 && keyLengthInBytes != 32) {
        promise->reject(nullptr);
        return;
    }

    CCCryptorRef cryptor;
#if PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
    CCAlgorithm aesAlgorithm = kCCAlgorithmAES;
#else
    CCAlgorithm aesAlgorithm = kCCAlgorithmAES128;
#endif
    CCCryptorStatus status = CCCryptorCreate(operation, aesAlgorithm, kCCOptionPKCS7Padding, key.key().data(), keyLengthInBytes, parameters.iv.data(), &cryptor);
    if (status) {
        promise->reject(nullptr);
        return;
    }

    Vector<uint8_t> result(CCCryptorGetOutputLength(cryptor, data.second, true));

    size_t bytesWritten;
    status = CCCryptorUpdate(cryptor, data.first, data.second, result.data(), result.size(), &bytesWritten);
    if (status) {
        promise->reject(nullptr);
        return;
    }

    uint8_t* p = result.data() + bytesWritten;
    status = CCCryptorFinal(cryptor, p, result.end() - p, &bytesWritten);
    p += bytesWritten;
    if (status) {
        promise->reject(nullptr);
        return;
    }

    ASSERT(p <= result.end());
    result.shrink(p - result.begin());

    CCCryptorRelease(cryptor);

    promise->fulfill(result);
}
Example #2
0
/* 
 * Test harness for CCCryptor with lots of options. 
 */
CCCryptorStatus doCCCrypt(
	bool forEncrypt,
	CCAlgorithm encrAlg,			
	bool doCbc,
	bool doPadding,
	const void *keyBytes, size_t keyLen,
	const void *iv,
	bool randUpdates,
	bool inPlace,								/* !doPadding only */
	size_t ctxSize,								/* if nonzero, we allocate ctx */
	bool askOutSize,
	const uint8_t *inText, size_t inTextLen,
	uint8_t **outText, size_t *outTextLen)		/* both returned, WE malloc */
{
	CCCryptorRef	cryptor = NULL;
	CCCryptorStatus crtn;
	CCOperation		op = forEncrypt ? kCCEncrypt : kCCDecrypt;
	CCOptions		options = 0;
	uint8_t			*outBuf = NULL;			/* mallocd output buffer */
	uint8_t			*outp;					/* running ptr into outBuf */
	const uint8		*inp;					/* running ptr into inText */
	size_t			outLen;					/* bytes remaining in outBuf */
	size_t			toMove;					/* bytes remaining in inText */
	size_t			thisMoveOut;			/* output from CCCryptUpdate()/CCCryptFinal() */
	size_t			outBytes;				/* total bytes actually produced in outBuf */
	char			ctx[CC_MAX_CTX_SIZE];	/* for CCCryptorCreateFromData() */
	uint8_t			*textMarker = NULL;		/* 8 bytes of marker here after expected end of 
											 * output */
	char			*ctxMarker = NULL;		/* ditto for caller-provided context */
	unsigned		dex;
	size_t			askedOutSize;			/* from the lib */
	size_t			thisOutLen;				/* dataOutAvailable we use */
	
	if(ctxSize > CC_MAX_CTX_SIZE) {
		printf("***HEY! Adjust CC_MAX_CTX_SIZE!\n");
		exit(1);
	}
	if(!doCbc) {
		options |= kCCOptionECBMode;
	}
	if(doPadding) {
		options |= kCCOptionPKCS7Padding;
	}
	
	/* just hack this one */
	outLen = inTextLen;
	if(forEncrypt) {
		outLen += MAX_BLOCK_SIZE;
	}
	
	outBuf = (uint8_t *)malloc(outLen + MARKER_LENGTH);
	memset(outBuf, 0xEE, outLen + MARKER_LENGTH);
	
	/* library should not touch this memory */
	textMarker = outBuf + outLen;
	memset(textMarker, MARKER_BYTE, MARKER_LENGTH);
	
	/* subsequent errors to errOut: */

	if(inPlace) {
		memmove(outBuf, inText, inTextLen);
		inp = outBuf;
	}
	else {
		inp = inText;
	}

	if(!randUpdates) {
		/* one shot */
		if(askOutSize) {
			crtn = CCCrypt(op, encrAlg, options,
				keyBytes, keyLen, iv,
				inp, inTextLen,
				outBuf, 0, &askedOutSize);
			if(crtn != kCCBufferTooSmall) {
				printf("***Did not get kCCBufferTooSmall as expected\n");
				printf("   alg %d inTextLen %lu cbc %d padding %d keyLen %lu\n",
					(int)encrAlg, (unsigned long)inTextLen, (int)doCbc, (int)doPadding,
					(unsigned long)keyLen);
				printCCError("CCCrypt", crtn);
				crtn = -1;
				goto errOut;
			}
			outLen = askedOutSize;
		}
		crtn = CCCrypt(op, encrAlg, options,
			keyBytes, keyLen, iv,
			inp, inTextLen,
			outBuf, outLen, &outLen);
		if(crtn) {
			printCCError("CCCrypt", crtn);
			goto errOut;
		}
		*outText = outBuf;
		*outTextLen = outLen;
		goto errOut;
	}
	
	/* random multi updates */
	if(ctxSize) {
		size_t ctxSizeCreated;
		
		if(askOutSize) {
			crtn = CCCryptorCreateFromData(op, encrAlg, options,
				keyBytes, keyLen, iv,
				ctx, 0 /* ctxSize */,
				&cryptor, &askedOutSize);
			if(crtn != kCCBufferTooSmall) {
				printf("***Did not get kCCBufferTooSmall as expected\n");
				printCCError("CCCryptorCreateFromData", crtn);
				crtn = -1;
				goto errOut;
			}
			ctxSize = askedOutSize;
		}
		crtn = CCCryptorCreateFromData(op, encrAlg, options,
			keyBytes, keyLen, iv,
			ctx, ctxSize, &cryptor, &ctxSizeCreated);
		if(crtn) {
			printCCError("CCCryptorCreateFromData", crtn);
			return crtn;
		}
		ctxMarker = ctx + ctxSizeCreated;
		memset(ctxMarker, MARKER_BYTE, MARKER_LENGTH);
	}
	else {
		crtn = CCCryptorCreate(op, encrAlg, options,
			keyBytes, keyLen, iv,
			&cryptor);
		if(crtn) {
			printCCError("CCCryptorCreate", crtn);
			return crtn;
		}
	}
	
	toMove = inTextLen;		/* total to go */
	outp = outBuf;
	outBytes = 0;			/* bytes actually produced in outBuf */
	
	while(toMove) {
		uint32 thisMoveIn;			/* input to CCryptUpdate() */
		
		thisMoveIn = genRand(1, toMove);
		logSize(("###ptext segment len %lu\n", (unsigned long)thisMoveIn)); 
		if(askOutSize) {
			thisOutLen = CCCryptorGetOutputLength(cryptor, thisMoveIn, false);
		}
		else {
			thisOutLen = outLen;
		}
		crtn = CCCryptorUpdate(cryptor, inp, thisMoveIn,
			outp, thisOutLen, &thisMoveOut);
		if(crtn) {
			printCCError("CCCryptorUpdate", crtn);
			goto errOut;
		}
		inp			+= thisMoveIn;
		toMove		-= thisMoveIn;
		outp		+= thisMoveOut;
		outLen   	-= thisMoveOut;
		outBytes	+= thisMoveOut;
	}
	
	if(doPadding) {
		/* Final is not needed if padding is disabled */
		if(askOutSize) {
			thisOutLen = CCCryptorGetOutputLength(cryptor, 0, true);
		}
		else {
			thisOutLen = outLen;
		}
		crtn = CCCryptorFinal(cryptor, outp, thisOutLen, &thisMoveOut);
	}
	else {
		thisMoveOut = 0;
		crtn = kCCSuccess;
	}
	
	if(crtn) {
		printCCError("CCCryptorFinal", crtn);
		goto errOut;
	}
	
	outBytes += thisMoveOut;
	*outText = outBuf;
	*outTextLen = outBytes;
	crtn = kCCSuccess;

	for(dex=0; dex<MARKER_LENGTH; dex++) {
		if(textMarker[dex] != MARKER_BYTE) {
			printf("***lib scribbled on our textMarker memory (op=%s)!\n",
				forEncrypt ? "encrypt" : "decrypt");
			crtn = (CCCryptorStatus)-1;
		}
	}
	if(ctxSize) {
		for(dex=0; dex<MARKER_LENGTH; dex++) {
			if(ctxMarker[dex] != MARKER_BYTE) {
				printf("***lib scribbled on our ctxMarker memory (op=%s)!\n",
					forEncrypt ? "encrypt" : "decrypt");
				crtn = (CCCryptorStatus)-1;
			}
		}
	}
	
errOut:
	if(crtn) {
		if(outBuf) {
			free(outBuf);
		}
	}
	if(cryptor) {
		CCCryptorRelease(cryptor);
	}
	return crtn;
}