1#include <stdio.h>
2#include <CommonCrypto/CommonCryptor.h>
3#include "testbyteBuffer.h"
4#include "testmore.h"
5#include "capabilities.h"
6
7#if (CCSYMOUTPUTLEN == 0)
8entryPoint(CommonCryptoOutputLength,"CommonCrypto Output Length Testing")
9#else
10
11static int kTestTestCount = 21912;
12
13#define MAXSTART 64
14#define MAXOUT 4096
15
16static int
17testOutputLength(CCOperation op, CCMode mode, CCAlgorithm alg, size_t keyLength, CCPadding padding, size_t bufferPos, size_t inputLength, bool final, size_t expectedLen)
18{
19    CCCryptorRef cryptorRef;
20    size_t retval;
21    CCCryptorStatus status;
22    uint8_t iv[16];
23    uint8_t key[16];
24    uint8_t dataIn[MAXSTART], dataOut[MAXOUT];
25    size_t moved = 0;
26
27    status = CCCryptorCreateWithMode(op, mode, alg, padding, iv, key, keyLength, NULL, 0, 1, kCCModeOptionCTR_BE, &cryptorRef);
28    ok(status == kCCSuccess, "Created Cryptor");
29    status = CCCryptorUpdate(cryptorRef, dataIn, bufferPos, dataOut, MAXOUT, &moved);
30    ok(status == kCCSuccess, "Setup Initial Internal Length");
31    retval = CCCryptorGetOutputLength(cryptorRef, inputLength, final);
32    ok(retval == expectedLen, "Got Length Value Expected");
33    if(retval != expectedLen) {
34        printf("bufferPos = %lu + inputLength = %lu Got %lu expected %lu\n", bufferPos, inputLength, retval, expectedLen);
35    }
36    status = CCCryptorRelease(cryptorRef);
37    ok(status == kCCSuccess, "Released Cryptor");
38    return -1;
39}
40
41static inline size_t round_down_by_blocksize(size_t len, size_t blocksize) {
42    return len / blocksize * blocksize;
43}
44
45static inline size_t pkcs7decryptUpdateResultLength_by_blocksize(size_t len, size_t blocksize) {
46    if(len <= blocksize) return 0;
47    if(!(len % blocksize)) return len - blocksize;
48    return round_down_by_blocksize(len, blocksize);
49}
50
51int CommonCryptoOutputLength (int argc, char *const *argv)
52{
53    int verbose = 0;
54	plan_tests(kTestTestCount);
55
56    /* ENCRYPTING ****************************************************************************************************************************************/
57    if(verbose) diag("ENCRYPTING AES-CTR (Streaming Mode) Update");
58    for(size_t i=0; i<3*kCCBlockSizeAES128; i++) {
59        for(size_t bufferPos=0; bufferPos<kCCBlockSizeAES128; bufferPos++) {
60            testOutputLength(kCCEncrypt, kCCModeCTR, kCCAlgorithmAES128, kCCKeySizeAES128, ccNoPadding, bufferPos, i, false, i);
61        }
62    }
63
64    if(verbose) diag("ENCRYPTING AES-ECB-NoPadding Update");
65    for(size_t i=0; i<3*kCCBlockSizeAES128; i++) {
66        for(size_t bufferPos=0; bufferPos<kCCBlockSizeAES128; bufferPos++) {
67            size_t total = i+bufferPos;
68            testOutputLength(kCCEncrypt, kCCModeECB, kCCAlgorithmAES128, kCCKeySizeAES128, ccNoPadding, bufferPos, i, false, total-(total%kCCBlockSizeAES128));
69        }
70    }
71
72    if(verbose) diag("ENCRYPTING 3DES-ECB-NoPadding Update");
73    for(size_t i=0; i<3*kCCBlockSize3DES; i++) {
74        for(size_t bufferPos=0; bufferPos<kCCBlockSize3DES; bufferPos++) {
75            size_t total = i+bufferPos;
76            testOutputLength(kCCEncrypt, kCCModeECB, kCCAlgorithm3DES, kCCKeySize3DES, ccNoPadding, bufferPos, i, false, total-(total%kCCBlockSize3DES));
77        }
78    }
79
80    if(verbose) diag("ENCRYPTING AES-CBC-PKCS7Padding Update");
81    for(size_t i=0; i<3*kCCBlockSizeAES128; i++) {
82        for(size_t bufferPos=0; bufferPos<kCCBlockSizeAES128; bufferPos++) {
83            size_t total = i+bufferPos;
84            testOutputLength(kCCEncrypt, kCCModeCBC, kCCAlgorithmAES128, kCCKeySizeAES128, ccPKCS7Padding, bufferPos, i, false, total-(total%kCCBlockSizeAES128));
85        }
86    }
87
88    if(verbose) diag("ENCRYPTING 3DES-CBC-PKCS7Padding Update");
89    for(size_t i=0; i<3*kCCBlockSize3DES; i++) {
90        for(size_t bufferPos=0; bufferPos<kCCBlockSize3DES; bufferPos++) {
91            size_t total = i+bufferPos;
92            testOutputLength(kCCEncrypt, kCCModeCBC, kCCAlgorithm3DES, kCCKeySize3DES, ccPKCS7Padding, bufferPos, i, false, total-(total%kCCBlockSize3DES));
93        }
94    }
95    if(verbose) diag("ENCRYPTING AES-CBC-PKCS7Padding-Final");
96    for(size_t i=0; i<3*kCCBlockSizeAES128; i++) {
97        for(size_t bufferPos=0; bufferPos<kCCBlockSizeAES128; bufferPos++) {
98            size_t total = i+bufferPos;
99            testOutputLength(kCCEncrypt, kCCModeCBC, kCCAlgorithmAES128, kCCKeySizeAES128, ccPKCS7Padding, bufferPos, i, true, total-(total%kCCBlockSizeAES128)+kCCBlockSizeAES128);
100        }
101    }
102
103    if(verbose) diag("ENCRYPTING 3DES-CBC-PKCS7Padding-Final");
104    for(size_t i=0; i<3*kCCBlockSize3DES; i++) {
105        for(size_t bufferPos=0; bufferPos<kCCBlockSize3DES; bufferPos++) {
106            size_t total = i+bufferPos;
107            testOutputLength(kCCEncrypt, kCCModeCBC, kCCAlgorithm3DES, kCCKeySize3DES, ccPKCS7Padding, bufferPos, i, true, total-(total%kCCBlockSize3DES)+kCCBlockSize3DES);
108        }
109    }
110
111    /* DECRYPTING ****************************************************************************************************************************************/
112
113    if(verbose) diag("DECRYPTING AES-CTR (Streaming Mode) Update");
114    for(size_t i=0; i<3*kCCBlockSizeAES128; i++) {
115        for(size_t bufferPos=0; bufferPos<kCCBlockSizeAES128; bufferPos++) {
116            testOutputLength(kCCDecrypt, kCCModeCTR, kCCAlgorithmAES128, kCCKeySizeAES128, ccNoPadding, bufferPos, i, false, i);
117        }
118    }
119
120    // From here down everything should be in full blocks
121    if(verbose) diag("DECRYPTING AES-ECB-NoPadding Update");
122    for(size_t i=0; i<3*kCCBlockSizeAES128; i+=kCCBlockSizeAES128) {
123        for(size_t bufferPos=0; bufferPos<kCCBlockSizeAES128; bufferPos++) {
124            size_t total = i+bufferPos;
125            testOutputLength(kCCDecrypt, kCCModeECB, kCCAlgorithmAES128, kCCKeySizeAES128, ccNoPadding, bufferPos, i, false, round_down_by_blocksize(total, kCCBlockSizeAES128));
126        }
127    }
128
129    if(verbose) diag("DECRYPTING 3DES-ECB-NoPadding Update");
130    for(size_t i=0; i<3*kCCBlockSizeAES128; i+=kCCBlockSizeAES128) {
131        for(size_t bufferPos=0; bufferPos<kCCBlockSizeAES128; bufferPos++) {
132            size_t total = i+bufferPos;
133            testOutputLength(kCCDecrypt, kCCModeECB, kCCAlgorithm3DES, kCCKeySize3DES, ccNoPadding, bufferPos, i, false, round_down_by_blocksize(total, kCCBlockSizeAES128));
134        }
135    }
136
137    if(verbose) diag("DECRYPTING AES-CBC-PKCS7Padding Update");
138    for(size_t i=0; i<3*kCCBlockSizeAES128; i++) {
139        for(size_t bufferPos=1; bufferPos <= kCCBlockSizeAES128; bufferPos ++) {
140            size_t total = pkcs7decryptUpdateResultLength_by_blocksize(i+bufferPos, kCCBlockSizeAES128);
141            testOutputLength(kCCDecrypt, kCCModeCBC, kCCAlgorithmAES128, kCCKeySizeAES128, ccPKCS7Padding, bufferPos, i, false, total);
142        }
143    }
144
145    if(verbose) diag("DECRYPTING 3DES-CBC-PKCS7Padding Update");
146    for(size_t i=0; i<3*kCCBlockSize3DES; i++) {
147        for(size_t bufferPos=1; bufferPos <= kCCBlockSize3DES; bufferPos ++) {
148            size_t total = pkcs7decryptUpdateResultLength_by_blocksize(i+bufferPos, kCCBlockSize3DES);
149            testOutputLength(kCCDecrypt, kCCModeCBC, kCCAlgorithm3DES, kCCKeySize3DES, ccPKCS7Padding, bufferPos, i, false, total);
150        }
151
152    }
153
154    if(verbose) diag("DECRYPTING AES-CBC-PKCS7Padding-Final");
155    for(size_t i=0; i<3*kCCBlockSizeAES128; i+=kCCBlockSizeAES128) {
156        size_t bufferPos=kCCBlockSizeAES128;
157        size_t total = i+bufferPos;
158        testOutputLength(kCCDecrypt, kCCModeCBC, kCCAlgorithmAES128, kCCKeySizeAES128, ccPKCS7Padding, bufferPos, i, true, total);
159    }
160
161    if(verbose) diag("DECRYPTING 3DES-CBC-PKCS7Padding-Final");
162    for(size_t i=0; i<3*kCCBlockSize3DES; i+=kCCBlockSize3DES) {
163        for(size_t bufferPos=0; bufferPos<kCCBlockSize3DES; bufferPos+=kCCBlockSize3DES) {
164            size_t bufferPos=kCCBlockSize3DES;
165            size_t total = i+bufferPos;
166            testOutputLength(kCCDecrypt, kCCModeCBC, kCCAlgorithm3DES, kCCKeySize3DES, ccPKCS7Padding, kCCBlockSize3DES, i, true, total);
167        }
168    }
169
170    return 0;
171}
172#endif /* CCSYMOUTPUTLEN */
173
174