Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | #include <stdio.h> |
michael@0 | 6 | #include <stdlib.h> |
michael@0 | 7 | #include <ctype.h> |
michael@0 | 8 | |
michael@0 | 9 | #include "pk11pub.h" |
michael@0 | 10 | #include "secerr.h" |
michael@0 | 11 | #include "nss.h" |
michael@0 | 12 | |
michael@0 | 13 | static SECStatus |
michael@0 | 14 | hex_to_byteval(const char *c2, unsigned char *byteval) |
michael@0 | 15 | { |
michael@0 | 16 | int i; |
michael@0 | 17 | unsigned char offset; |
michael@0 | 18 | *byteval = 0; |
michael@0 | 19 | for (i=0; i<2; i++) { |
michael@0 | 20 | if (c2[i] >= '0' && c2[i] <= '9') { |
michael@0 | 21 | offset = c2[i] - '0'; |
michael@0 | 22 | *byteval |= offset << 4*(1-i); |
michael@0 | 23 | } else if (c2[i] >= 'a' && c2[i] <= 'f') { |
michael@0 | 24 | offset = c2[i] - 'a'; |
michael@0 | 25 | *byteval |= (offset + 10) << 4*(1-i); |
michael@0 | 26 | } else if (c2[i] >= 'A' && c2[i] <= 'F') { |
michael@0 | 27 | offset = c2[i] - 'A'; |
michael@0 | 28 | *byteval |= (offset + 10) << 4*(1-i); |
michael@0 | 29 | } else { |
michael@0 | 30 | return SECFailure; |
michael@0 | 31 | } |
michael@0 | 32 | } |
michael@0 | 33 | return SECSuccess; |
michael@0 | 34 | } |
michael@0 | 35 | |
michael@0 | 36 | static SECStatus |
michael@0 | 37 | aes_encrypt_buf( |
michael@0 | 38 | const unsigned char *key, unsigned int keysize, |
michael@0 | 39 | const unsigned char *iv, unsigned int ivsize, |
michael@0 | 40 | unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, |
michael@0 | 41 | const unsigned char *input, unsigned int inputlen, |
michael@0 | 42 | const unsigned char *aad, unsigned int aadlen, unsigned int tagsize) |
michael@0 | 43 | { |
michael@0 | 44 | SECStatus rv = SECFailure; |
michael@0 | 45 | SECItem key_item; |
michael@0 | 46 | PK11SlotInfo* slot = NULL; |
michael@0 | 47 | PK11SymKey *symKey = NULL; |
michael@0 | 48 | CK_GCM_PARAMS gcm_params; |
michael@0 | 49 | SECItem param; |
michael@0 | 50 | |
michael@0 | 51 | /* Import key into NSS. */ |
michael@0 | 52 | key_item.type = siBuffer; |
michael@0 | 53 | key_item.data = (unsigned char *) key; /* const cast */ |
michael@0 | 54 | key_item.len = keysize; |
michael@0 | 55 | slot = PK11_GetInternalSlot(); |
michael@0 | 56 | symKey = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap, |
michael@0 | 57 | CKA_ENCRYPT, &key_item, NULL); |
michael@0 | 58 | PK11_FreeSlot(slot); |
michael@0 | 59 | slot = NULL; |
michael@0 | 60 | if (!symKey) { |
michael@0 | 61 | fprintf(stderr, "PK11_ImportSymKey failed\n"); |
michael@0 | 62 | goto loser; |
michael@0 | 63 | } |
michael@0 | 64 | |
michael@0 | 65 | gcm_params.pIv = (unsigned char *) iv; /* const cast */ |
michael@0 | 66 | gcm_params.ulIvLen = ivsize; |
michael@0 | 67 | gcm_params.pAAD = (unsigned char *) aad; /* const cast */ |
michael@0 | 68 | gcm_params.ulAADLen = aadlen; |
michael@0 | 69 | gcm_params.ulTagBits = tagsize * 8; |
michael@0 | 70 | |
michael@0 | 71 | param.type = siBuffer; |
michael@0 | 72 | param.data = (unsigned char *) &gcm_params; |
michael@0 | 73 | param.len = sizeof(gcm_params); |
michael@0 | 74 | |
michael@0 | 75 | if (PK11_Encrypt(symKey, CKM_AES_GCM, ¶m, |
michael@0 | 76 | output, outputlen, maxoutputlen, |
michael@0 | 77 | input, inputlen) != SECSuccess) { |
michael@0 | 78 | fprintf(stderr, "PK11_Encrypt failed\n"); |
michael@0 | 79 | goto loser; |
michael@0 | 80 | } |
michael@0 | 81 | |
michael@0 | 82 | rv = SECSuccess; |
michael@0 | 83 | |
michael@0 | 84 | loser: |
michael@0 | 85 | if (symKey != NULL) { |
michael@0 | 86 | PK11_FreeSymKey(symKey); |
michael@0 | 87 | } |
michael@0 | 88 | return rv; |
michael@0 | 89 | } |
michael@0 | 90 | |
michael@0 | 91 | static SECStatus |
michael@0 | 92 | aes_decrypt_buf( |
michael@0 | 93 | const unsigned char *key, unsigned int keysize, |
michael@0 | 94 | const unsigned char *iv, unsigned int ivsize, |
michael@0 | 95 | unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, |
michael@0 | 96 | const unsigned char *input, unsigned int inputlen, |
michael@0 | 97 | const unsigned char *aad, unsigned int aadlen, |
michael@0 | 98 | const unsigned char *tag, unsigned int tagsize) |
michael@0 | 99 | { |
michael@0 | 100 | SECStatus rv = SECFailure; |
michael@0 | 101 | unsigned char concatenated[11*16]; /* 1 to 11 blocks */ |
michael@0 | 102 | SECItem key_item; |
michael@0 | 103 | PK11SlotInfo *slot = NULL; |
michael@0 | 104 | PK11SymKey *symKey = NULL; |
michael@0 | 105 | CK_GCM_PARAMS gcm_params; |
michael@0 | 106 | SECItem param; |
michael@0 | 107 | |
michael@0 | 108 | if (inputlen + tagsize > sizeof(concatenated)) { |
michael@0 | 109 | fprintf(stderr, "aes_decrypt_buf: local buffer too small\n"); |
michael@0 | 110 | goto loser; |
michael@0 | 111 | } |
michael@0 | 112 | memcpy(concatenated, input, inputlen); |
michael@0 | 113 | memcpy(concatenated + inputlen, tag, tagsize); |
michael@0 | 114 | |
michael@0 | 115 | /* Import key into NSS. */ |
michael@0 | 116 | key_item.type = siBuffer; |
michael@0 | 117 | key_item.data = (unsigned char *) key; /* const cast */ |
michael@0 | 118 | key_item.len = keysize; |
michael@0 | 119 | slot = PK11_GetInternalSlot(); |
michael@0 | 120 | symKey = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap, |
michael@0 | 121 | CKA_DECRYPT, &key_item, NULL); |
michael@0 | 122 | PK11_FreeSlot(slot); |
michael@0 | 123 | slot = NULL; |
michael@0 | 124 | if (!symKey) { |
michael@0 | 125 | fprintf(stderr, "PK11_ImportSymKey failed\n"); |
michael@0 | 126 | goto loser; |
michael@0 | 127 | } |
michael@0 | 128 | |
michael@0 | 129 | gcm_params.pIv = (unsigned char *) iv; |
michael@0 | 130 | gcm_params.ulIvLen = ivsize; |
michael@0 | 131 | gcm_params.pAAD = (unsigned char *) aad; |
michael@0 | 132 | gcm_params.ulAADLen = aadlen; |
michael@0 | 133 | gcm_params.ulTagBits = tagsize * 8; |
michael@0 | 134 | |
michael@0 | 135 | param.type = siBuffer; |
michael@0 | 136 | param.data = (unsigned char *) &gcm_params; |
michael@0 | 137 | param.len = sizeof(gcm_params); |
michael@0 | 138 | |
michael@0 | 139 | if (PK11_Decrypt(symKey, CKM_AES_GCM, ¶m, |
michael@0 | 140 | output, outputlen, maxoutputlen, |
michael@0 | 141 | concatenated, inputlen + tagsize) != SECSuccess) { |
michael@0 | 142 | goto loser; |
michael@0 | 143 | } |
michael@0 | 144 | |
michael@0 | 145 | rv = SECSuccess; |
michael@0 | 146 | |
michael@0 | 147 | loser: |
michael@0 | 148 | if (symKey != NULL) { |
michael@0 | 149 | PK11_FreeSymKey(symKey); |
michael@0 | 150 | } |
michael@0 | 151 | return rv; |
michael@0 | 152 | } |
michael@0 | 153 | |
michael@0 | 154 | /* |
michael@0 | 155 | * Perform the AES Known Answer Test (KAT) in Galois Counter Mode (GCM). |
michael@0 | 156 | * |
michael@0 | 157 | * respfn is the pathname of the RESPONSE file. |
michael@0 | 158 | */ |
michael@0 | 159 | static void |
michael@0 | 160 | aes_gcm_kat(const char *respfn) |
michael@0 | 161 | { |
michael@0 | 162 | char buf[512]; /* holds one line from the input REQUEST file. |
michael@0 | 163 | * needs to be large enough to hold the longest |
michael@0 | 164 | * line "CIPHERTEXT = <320 hex digits>\n". |
michael@0 | 165 | */ |
michael@0 | 166 | FILE *aesresp; /* input stream from the RESPONSE file */ |
michael@0 | 167 | int i, j; |
michael@0 | 168 | unsigned int test_group = 0; |
michael@0 | 169 | unsigned int num_tests; |
michael@0 | 170 | PRBool is_encrypt; |
michael@0 | 171 | unsigned char key[32]; /* 128, 192, or 256 bits */ |
michael@0 | 172 | unsigned int keysize; |
michael@0 | 173 | unsigned char iv[10*16]; /* 1 to 10 blocks */ |
michael@0 | 174 | unsigned int ivsize; |
michael@0 | 175 | unsigned char plaintext[10*16]; /* 1 to 10 blocks */ |
michael@0 | 176 | unsigned int plaintextlen = 0; |
michael@0 | 177 | unsigned char aad[10*16]; /* 1 to 10 blocks */ |
michael@0 | 178 | unsigned int aadlen = 0; |
michael@0 | 179 | unsigned char ciphertext[10*16]; /* 1 to 10 blocks */ |
michael@0 | 180 | unsigned int ciphertextlen; |
michael@0 | 181 | unsigned char tag[16]; |
michael@0 | 182 | unsigned int tagsize; |
michael@0 | 183 | unsigned char output[10*16]; /* 1 to 10 blocks */ |
michael@0 | 184 | unsigned int outputlen; |
michael@0 | 185 | |
michael@0 | 186 | unsigned int expected_keylen = 0; |
michael@0 | 187 | unsigned int expected_ivlen = 0; |
michael@0 | 188 | unsigned int expected_ptlen = 0; |
michael@0 | 189 | unsigned int expected_aadlen = 0; |
michael@0 | 190 | unsigned int expected_taglen = 0; |
michael@0 | 191 | SECStatus rv; |
michael@0 | 192 | |
michael@0 | 193 | if (strstr(respfn, "Encrypt") != NULL) { |
michael@0 | 194 | is_encrypt = PR_TRUE; |
michael@0 | 195 | } else if (strstr(respfn, "Decrypt") != NULL) { |
michael@0 | 196 | is_encrypt = PR_FALSE; |
michael@0 | 197 | } else { |
michael@0 | 198 | fprintf(stderr, "Input file name must contain Encrypt or Decrypt\n"); |
michael@0 | 199 | exit(1); |
michael@0 | 200 | } |
michael@0 | 201 | aesresp = fopen(respfn, "r"); |
michael@0 | 202 | if (aesresp == NULL) { |
michael@0 | 203 | fprintf(stderr, "Cannot open input file %s\n", respfn); |
michael@0 | 204 | exit(1); |
michael@0 | 205 | } |
michael@0 | 206 | while (fgets(buf, sizeof buf, aesresp) != NULL) { |
michael@0 | 207 | /* a comment or blank line */ |
michael@0 | 208 | if (buf[0] == '#' || buf[0] == '\n') { |
michael@0 | 209 | continue; |
michael@0 | 210 | } |
michael@0 | 211 | /* [Keylen = ...], [IVlen = ...], etc. */ |
michael@0 | 212 | if (buf[0] == '[') { |
michael@0 | 213 | if (strncmp(&buf[1], "Keylen = ", 9) == 0) { |
michael@0 | 214 | expected_keylen = atoi(&buf[10]); |
michael@0 | 215 | } else if (strncmp(&buf[1], "IVlen = ", 8) == 0) { |
michael@0 | 216 | expected_ivlen = atoi(&buf[9]); |
michael@0 | 217 | } else if (strncmp(&buf[1], "PTlen = ", 8) == 0) { |
michael@0 | 218 | expected_ptlen = atoi(&buf[9]); |
michael@0 | 219 | } else if (strncmp(&buf[1], "AADlen = ", 9) == 0) { |
michael@0 | 220 | expected_aadlen = atoi(&buf[10]); |
michael@0 | 221 | } else if (strncmp(&buf[1], "Taglen = ", 9) == 0) { |
michael@0 | 222 | expected_taglen = atoi(&buf[10]); |
michael@0 | 223 | |
michael@0 | 224 | test_group++; |
michael@0 | 225 | if (test_group > 1) { |
michael@0 | 226 | /* Report num_tests for the previous test group. */ |
michael@0 | 227 | printf("%u tests\n", num_tests); |
michael@0 | 228 | } |
michael@0 | 229 | num_tests = 0; |
michael@0 | 230 | printf("Keylen = %u, IVlen = %u, PTlen = %u, AADlen = %u, " |
michael@0 | 231 | "Taglen = %u: ", expected_keylen, expected_ivlen, |
michael@0 | 232 | expected_ptlen, expected_aadlen, expected_taglen); |
michael@0 | 233 | /* Convert lengths in bits to lengths in bytes. */ |
michael@0 | 234 | PORT_Assert(expected_keylen % 8 == 0); |
michael@0 | 235 | expected_keylen /= 8; |
michael@0 | 236 | PORT_Assert(expected_ivlen % 8 == 0); |
michael@0 | 237 | expected_ivlen /= 8; |
michael@0 | 238 | PORT_Assert(expected_ptlen % 8 == 0); |
michael@0 | 239 | expected_ptlen /= 8; |
michael@0 | 240 | PORT_Assert(expected_aadlen % 8 == 0); |
michael@0 | 241 | expected_aadlen /= 8; |
michael@0 | 242 | PORT_Assert(expected_taglen % 8 == 0); |
michael@0 | 243 | expected_taglen /= 8; |
michael@0 | 244 | } else { |
michael@0 | 245 | fprintf(stderr, "Unexpected input line: %s\n", buf); |
michael@0 | 246 | exit(1); |
michael@0 | 247 | } |
michael@0 | 248 | continue; |
michael@0 | 249 | } |
michael@0 | 250 | /* "Count = x" begins a new data set */ |
michael@0 | 251 | if (strncmp(buf, "Count", 5) == 0) { |
michael@0 | 252 | /* zeroize the variables for the test with this data set */ |
michael@0 | 253 | memset(key, 0, sizeof key); |
michael@0 | 254 | keysize = 0; |
michael@0 | 255 | memset(iv, 0, sizeof iv); |
michael@0 | 256 | ivsize = 0; |
michael@0 | 257 | memset(plaintext, 0, sizeof plaintext); |
michael@0 | 258 | plaintextlen = 0; |
michael@0 | 259 | memset(aad, 0, sizeof aad); |
michael@0 | 260 | aadlen = 0; |
michael@0 | 261 | memset(ciphertext, 0, sizeof ciphertext); |
michael@0 | 262 | ciphertextlen = 0; |
michael@0 | 263 | memset(output, 0, sizeof output); |
michael@0 | 264 | outputlen = 0; |
michael@0 | 265 | num_tests++; |
michael@0 | 266 | continue; |
michael@0 | 267 | } |
michael@0 | 268 | /* Key = ... */ |
michael@0 | 269 | if (strncmp(buf, "Key", 3) == 0) { |
michael@0 | 270 | i = 3; |
michael@0 | 271 | while (isspace(buf[i]) || buf[i] == '=') { |
michael@0 | 272 | i++; |
michael@0 | 273 | } |
michael@0 | 274 | for (j=0; isxdigit(buf[i]); i+=2,j++) { |
michael@0 | 275 | hex_to_byteval(&buf[i], &key[j]); |
michael@0 | 276 | } |
michael@0 | 277 | keysize = j; |
michael@0 | 278 | if (keysize != expected_keylen) { |
michael@0 | 279 | fprintf(stderr, "Unexpected key length: %u vs. %u\n", |
michael@0 | 280 | keysize, expected_keylen); |
michael@0 | 281 | exit(1); |
michael@0 | 282 | } |
michael@0 | 283 | continue; |
michael@0 | 284 | } |
michael@0 | 285 | /* IV = ... */ |
michael@0 | 286 | if (strncmp(buf, "IV", 2) == 0) { |
michael@0 | 287 | i = 2; |
michael@0 | 288 | while (isspace(buf[i]) || buf[i] == '=') { |
michael@0 | 289 | i++; |
michael@0 | 290 | } |
michael@0 | 291 | for (j=0; isxdigit(buf[i]); i+=2,j++) { |
michael@0 | 292 | hex_to_byteval(&buf[i], &iv[j]); |
michael@0 | 293 | } |
michael@0 | 294 | ivsize = j; |
michael@0 | 295 | if (ivsize != expected_ivlen) { |
michael@0 | 296 | fprintf(stderr, "Unexpected IV length: %u vs. %u\n", |
michael@0 | 297 | ivsize, expected_ivlen); |
michael@0 | 298 | exit(1); |
michael@0 | 299 | } |
michael@0 | 300 | continue; |
michael@0 | 301 | } |
michael@0 | 302 | /* PT = ... */ |
michael@0 | 303 | if (strncmp(buf, "PT", 2) == 0) { |
michael@0 | 304 | i = 2; |
michael@0 | 305 | while (isspace(buf[i]) || buf[i] == '=') { |
michael@0 | 306 | i++; |
michael@0 | 307 | } |
michael@0 | 308 | for (j=0; isxdigit(buf[i]); i+=2,j++) { |
michael@0 | 309 | hex_to_byteval(&buf[i], &plaintext[j]); |
michael@0 | 310 | } |
michael@0 | 311 | plaintextlen = j; |
michael@0 | 312 | if (plaintextlen != expected_ptlen) { |
michael@0 | 313 | fprintf(stderr, "Unexpected PT length: %u vs. %u\n", |
michael@0 | 314 | plaintextlen, expected_ptlen); |
michael@0 | 315 | exit(1); |
michael@0 | 316 | } |
michael@0 | 317 | |
michael@0 | 318 | if (!is_encrypt) { |
michael@0 | 319 | rv = aes_decrypt_buf(key, keysize, iv, ivsize, |
michael@0 | 320 | output, &outputlen, sizeof output, |
michael@0 | 321 | ciphertext, ciphertextlen, aad, aadlen, tag, tagsize); |
michael@0 | 322 | if (rv != SECSuccess) { |
michael@0 | 323 | fprintf(stderr, "aes_decrypt_buf failed\n"); |
michael@0 | 324 | goto loser; |
michael@0 | 325 | } |
michael@0 | 326 | if (outputlen != plaintextlen) { |
michael@0 | 327 | fprintf(stderr, "aes_decrypt_buf: wrong output size\n"); |
michael@0 | 328 | goto loser; |
michael@0 | 329 | } |
michael@0 | 330 | if (memcmp(output, plaintext, plaintextlen) != 0) { |
michael@0 | 331 | fprintf(stderr, "aes_decrypt_buf: wrong plaintext\n"); |
michael@0 | 332 | goto loser; |
michael@0 | 333 | } |
michael@0 | 334 | } |
michael@0 | 335 | continue; |
michael@0 | 336 | } |
michael@0 | 337 | /* FAIL */ |
michael@0 | 338 | if (strncmp(buf, "FAIL", 4) == 0) { |
michael@0 | 339 | plaintextlen = 0; |
michael@0 | 340 | |
michael@0 | 341 | PORT_Assert(!is_encrypt); |
michael@0 | 342 | rv = aes_decrypt_buf(key, keysize, iv, ivsize, |
michael@0 | 343 | output, &outputlen, sizeof output, |
michael@0 | 344 | ciphertext, ciphertextlen, aad, aadlen, tag, tagsize); |
michael@0 | 345 | if (rv != SECFailure) { |
michael@0 | 346 | fprintf(stderr, "aes_decrypt_buf succeeded unexpectedly\n"); |
michael@0 | 347 | goto loser; |
michael@0 | 348 | } |
michael@0 | 349 | if (PORT_GetError() != SEC_ERROR_BAD_DATA) { |
michael@0 | 350 | fprintf(stderr, "aes_decrypt_buf failed with incorrect " |
michael@0 | 351 | "error code\n"); |
michael@0 | 352 | goto loser; |
michael@0 | 353 | } |
michael@0 | 354 | continue; |
michael@0 | 355 | } |
michael@0 | 356 | /* AAD = ... */ |
michael@0 | 357 | if (strncmp(buf, "AAD", 3) == 0) { |
michael@0 | 358 | i = 3; |
michael@0 | 359 | while (isspace(buf[i]) || buf[i] == '=') { |
michael@0 | 360 | i++; |
michael@0 | 361 | } |
michael@0 | 362 | for (j=0; isxdigit(buf[i]); i+=2,j++) { |
michael@0 | 363 | hex_to_byteval(&buf[i], &aad[j]); |
michael@0 | 364 | } |
michael@0 | 365 | aadlen = j; |
michael@0 | 366 | if (aadlen != expected_aadlen) { |
michael@0 | 367 | fprintf(stderr, "Unexpected AAD length: %u vs. %u\n", |
michael@0 | 368 | aadlen, expected_aadlen); |
michael@0 | 369 | exit(1); |
michael@0 | 370 | } |
michael@0 | 371 | continue; |
michael@0 | 372 | } |
michael@0 | 373 | /* CT = ... */ |
michael@0 | 374 | if (strncmp(buf, "CT", 2) == 0) { |
michael@0 | 375 | i = 2; |
michael@0 | 376 | while (isspace(buf[i]) || buf[i] == '=') { |
michael@0 | 377 | i++; |
michael@0 | 378 | } |
michael@0 | 379 | for (j=0; isxdigit(buf[i]); i+=2,j++) { |
michael@0 | 380 | hex_to_byteval(&buf[i], &ciphertext[j]); |
michael@0 | 381 | } |
michael@0 | 382 | ciphertextlen = j; |
michael@0 | 383 | if (ciphertextlen != expected_ptlen) { |
michael@0 | 384 | fprintf(stderr, "Unexpected CT length: %u vs. %u\n", |
michael@0 | 385 | ciphertextlen, expected_ptlen); |
michael@0 | 386 | exit(1); |
michael@0 | 387 | } |
michael@0 | 388 | continue; |
michael@0 | 389 | } |
michael@0 | 390 | /* Tag = ... */ |
michael@0 | 391 | if (strncmp(buf, "Tag", 3) == 0) { |
michael@0 | 392 | i = 3; |
michael@0 | 393 | while (isspace(buf[i]) || buf[i] == '=') { |
michael@0 | 394 | i++; |
michael@0 | 395 | } |
michael@0 | 396 | for (j=0; isxdigit(buf[i]); i+=2,j++) { |
michael@0 | 397 | hex_to_byteval(&buf[i], &tag[j]); |
michael@0 | 398 | } |
michael@0 | 399 | tagsize = j; |
michael@0 | 400 | if (tagsize != expected_taglen) { |
michael@0 | 401 | fprintf(stderr, "Unexpected tag length: %u vs. %u\n", |
michael@0 | 402 | tagsize, expected_taglen); |
michael@0 | 403 | exit(1); |
michael@0 | 404 | } |
michael@0 | 405 | |
michael@0 | 406 | if (is_encrypt) { |
michael@0 | 407 | rv = aes_encrypt_buf(key, keysize, iv, ivsize, |
michael@0 | 408 | output, &outputlen, sizeof output, |
michael@0 | 409 | plaintext, plaintextlen, aad, aadlen, tagsize); |
michael@0 | 410 | if (rv != SECSuccess) { |
michael@0 | 411 | fprintf(stderr, "aes_encrypt_buf failed\n"); |
michael@0 | 412 | goto loser; |
michael@0 | 413 | } |
michael@0 | 414 | if (outputlen != plaintextlen + tagsize) { |
michael@0 | 415 | fprintf(stderr, "aes_encrypt_buf: wrong output size\n"); |
michael@0 | 416 | goto loser; |
michael@0 | 417 | } |
michael@0 | 418 | if (memcmp(output, ciphertext, plaintextlen) != 0) { |
michael@0 | 419 | fprintf(stderr, "aes_encrypt_buf: wrong ciphertext\n"); |
michael@0 | 420 | goto loser; |
michael@0 | 421 | } |
michael@0 | 422 | if (memcmp(output + plaintextlen, tag, tagsize) != 0) { |
michael@0 | 423 | fprintf(stderr, "aes_encrypt_buf: wrong tag\n"); |
michael@0 | 424 | goto loser; |
michael@0 | 425 | } |
michael@0 | 426 | } |
michael@0 | 427 | continue; |
michael@0 | 428 | } |
michael@0 | 429 | } |
michael@0 | 430 | /* Report num_tests for the last test group. */ |
michael@0 | 431 | printf("%u tests\n", num_tests); |
michael@0 | 432 | printf("%u test groups\n", test_group); |
michael@0 | 433 | printf("PASS\n"); |
michael@0 | 434 | loser: |
michael@0 | 435 | fclose(aesresp); |
michael@0 | 436 | } |
michael@0 | 437 | |
michael@0 | 438 | int main(int argc, char **argv) |
michael@0 | 439 | { |
michael@0 | 440 | if (argc < 2) exit(1); |
michael@0 | 441 | |
michael@0 | 442 | NSS_NoDB_Init(NULL); |
michael@0 | 443 | |
michael@0 | 444 | /*************/ |
michael@0 | 445 | /* AES */ |
michael@0 | 446 | /*************/ |
michael@0 | 447 | if (strcmp(argv[1], "aes") == 0) { |
michael@0 | 448 | /* argv[2]=kat argv[3]=gcm argv[4]=<test name>.rsp */ |
michael@0 | 449 | if (strcmp(argv[2], "kat") == 0) { |
michael@0 | 450 | /* Known Answer Test (KAT) */ |
michael@0 | 451 | aes_gcm_kat(argv[4]); |
michael@0 | 452 | } |
michael@0 | 453 | } |
michael@0 | 454 | |
michael@0 | 455 | NSS_Shutdown(); |
michael@0 | 456 | return 0; |
michael@0 | 457 | } |