aes_calc.c (5477B)
1 /* 2 * aes_calc.c 3 * 4 * A simple AES calculator for generating AES encryption values 5 * 6 * David A. McGrew 7 * Cisco Systems, Inc. 8 */ 9 10 /* 11 * 12 * Copyright (c) 2001-2017, Cisco Systems, Inc. 13 * All rights reserved. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 19 * Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 22 * Redistributions in binary form must reproduce the above 23 * copyright notice, this list of conditions and the following 24 * disclaimer in the documentation and/or other materials provided 25 * with the distribution. 26 * 27 * Neither the name of the Cisco Systems, Inc. nor the names of its 28 * contributors may be used to endorse or promote products derived 29 * from this software without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 34 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 35 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 36 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 38 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 42 * OF THE POSSIBILITY OF SUCH DAMAGE. 43 * 44 */ 45 46 /* 47 48 Example usage (with first NIST FIPS 197 test case): 49 50 [sh]$ test/aes_calc 000102030405060708090a0b0c0d0e0f \ 51 00112233445566778899aabbccddeeff -v 52 53 plaintext: 00112233445566778899aabbccddeeff 54 key: 000102030405060708090a0b0c0d0e0f 55 ciphertext: 69c4e0d86a7b0430d8cdb78070b4c55a 56 57 */ 58 59 #ifdef HAVE_CONFIG_H 60 #include <config.h> 61 #endif 62 63 #include "aes.h" 64 #include <stdio.h> 65 #include <string.h> 66 #include "util.h" 67 68 void usage(char *prog_name) 69 { 70 printf("usage: %s <key> <plaintext> [<ciphertext>] [-v]\n", prog_name); 71 exit(255); 72 } 73 74 #define AES_MAX_KEY_LEN 32 75 76 int main(int argc, char *argv[]) 77 { 78 const char *expected_ciphertext = NULL; 79 const char *ciphertext = NULL; 80 v128_t data; 81 uint8_t key[AES_MAX_KEY_LEN]; 82 srtp_aes_expanded_key_t exp_key; 83 int key_len, len; 84 int verbose = 0; 85 srtp_err_status_t status; 86 87 /* -v must be last if it's passed */ 88 if (argc > 0 && strncmp(argv[argc - 1], "-v", 2) == 0) { 89 /* we're in verbose mode */ 90 verbose = 1; 91 --argc; 92 } 93 94 if (argc < 3 || argc > 4) { 95 /* we've been fed the wrong number of arguments - compain and exit */ 96 usage(argv[0]); 97 } 98 99 if (argc == 4) { 100 /* we're being passed the ciphertext to check (in unit test mode) */ 101 expected_ciphertext = argv[3]; 102 if (strlen(expected_ciphertext) != 16 * 2) { 103 usage(argv[0]); 104 } 105 } 106 107 /* read in key, checking length */ 108 if (strlen(argv[1]) > AES_MAX_KEY_LEN * 2) { 109 fprintf(stderr, 110 "error: too many digits in key " 111 "(should be at most %d hexadecimal digits, found %u)\n", 112 AES_MAX_KEY_LEN * 2, (unsigned)strlen(argv[1])); 113 exit(1); 114 } 115 len = hex_string_to_octet_string((char *)key, argv[1], AES_MAX_KEY_LEN * 2); 116 /* check that hex string is the right length */ 117 if (len != 32 && len != 48 && len != 64) { 118 fprintf(stderr, 119 "error: bad number of digits in key " 120 "(should be 32/48/64 hexadecimal digits, found %d)\n", 121 len); 122 exit(1); 123 } 124 key_len = len / 2; 125 126 /* read in plaintext, checking length */ 127 if (strlen(argv[2]) > 16 * 2) { 128 fprintf(stderr, 129 "error: too many digits in plaintext " 130 "(should be %d hexadecimal digits, found %u)\n", 131 16 * 2, (unsigned)strlen(argv[2])); 132 exit(1); 133 } 134 len = hex_string_to_octet_string((char *)(&data), argv[2], 16 * 2); 135 /* check that hex string is the right length */ 136 if (len < 16 * 2) { 137 fprintf(stderr, 138 "error: too few digits in plaintext " 139 "(should be %d hexadecimal digits, found %d)\n", 140 16 * 2, len); 141 exit(1); 142 } 143 144 if (verbose) { 145 /* print out plaintext */ 146 printf("plaintext:\t%s\n", 147 octet_string_hex_string((uint8_t *)&data, 16)); 148 } 149 150 /* encrypt plaintext */ 151 status = srtp_aes_expand_encryption_key(key, key_len, &exp_key); 152 if (status) { 153 fprintf(stderr, "error: AES key expansion failed.\n"); 154 exit(1); 155 } 156 157 srtp_aes_encrypt(&data, &exp_key); 158 159 /* write ciphertext to output */ 160 if (verbose) { 161 printf("key:\t\t%s\n", octet_string_hex_string(key, key_len)); 162 printf("ciphertext:\t"); 163 } 164 165 ciphertext = v128_hex_string(&data); 166 printf("%s\n", ciphertext); 167 168 if (expected_ciphertext && strcmp(ciphertext, expected_ciphertext) != 0) { 169 fprintf(stderr, 170 "error: calculated ciphertext %s does not match " 171 "expected ciphertext %s\n", 172 ciphertext, expected_ciphertext); 173 exit(1); 174 } 175 176 return 0; 177 }