1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2016 Nexenta Systems, Inc. All rights reserved. 14 * Copyright 2019 Joyent, Inc. 15 */ 16 17 #define __EXTENSIONS__ 18 #include <limits.h> 19 #include <strings.h> 20 #include <stdlib.h> 21 #include <stdio.h> 22 #include <sys/debug.h> 23 #include "cryptotest.h" 24 25 /* 26 * A somewhat arbitrary size that should be large enough to hold the printed 27 * error and size messages. 28 */ 29 #define BUFSZ 128 30 31 #define EXIT_FAILURE_MULTIPART 1 32 #define EXIT_FAILURE_SINGLEPART 2 33 34 test_fg_t cryptotest_decr_fg = { 35 .tf_fg = CRYPTO_FG_DECRYPT, 36 .tf_init = decrypt_init, 37 .tf_single = decrypt_single, 38 .tf_update = decrypt_update, 39 .tf_final = decrypt_final 40 }; 41 42 test_fg_t cryptotest_encr_fg = { 43 .tf_fg = CRYPTO_FG_ENCRYPT, 44 .tf_init = encrypt_init, 45 .tf_single = encrypt_single, 46 .tf_update = encrypt_update, 47 .tf_final = encrypt_final 48 }; 49 50 test_fg_t cryptotest_mac_fg = { 51 .tf_fg = CRYPTO_FG_MAC, 52 .tf_init = mac_init, 53 .tf_single = mac_single, 54 .tf_update = mac_update, 55 .tf_final = mac_final 56 }; 57 58 test_fg_t cryptotest_digest_fg = { 59 .tf_fg = CRYPTO_FG_DIGEST, 60 .tf_init = digest_init, 61 .tf_single = digest_single, 62 .tf_update = digest_update, 63 .tf_final = digest_final 64 }; 65 66 /* 67 * Utils 68 */ 69 70 static const char * 71 ctest_errstr(int e, char *buf, size_t buflen) 72 { 73 const char *name = NULL; 74 ; 75 switch (e) { 76 case CTEST_INIT_FAILED: 77 name = "CTEST_INIT_FAILED"; 78 break; 79 case CTEST_NAME_RESOLVE_FAILED: 80 name = "CTEST_MECH_NO_PROVIDER"; 81 break; 82 case CTEST_MECH_NO_PROVIDER: 83 name = "CTEST_MECH_NO_PROVIDER"; 84 break; 85 default: 86 name = "Unknown fatal error"; 87 break; 88 } 89 90 (void) snprintf(buf, buflen, "%s (%d)", name, e); 91 return (buf); 92 } 93 94 void 95 printbuf(uint8_t *buf, char *name, size_t size) 96 { 97 size_t i; 98 99 flockfile(stderr); 100 (void) fprintf(stderr, "%s%s", name, (size > 0) ? " " : ""); 101 for (i = 0; i < size; i++) 102 (void) fprintf(stderr, "%02x", buf[i]); 103 (void) fputc('\n', stderr); 104 funlockfile(stderr); 105 } 106 107 int 108 bufcmp(uint8_t *auth, uint8_t *cmp, size_t size) 109 { 110 if (memcmp(cmp, auth, size) != 0) { 111 (void) fprintf(stderr, " mismatched result\n\n"); 112 printbuf(cmp, "calc", size); 113 printbuf(auth, "orig", size); 114 return (1); 115 } else { 116 (void) fprintf(stderr, " result matches\n\n"); 117 return (0); 118 } 119 } 120 121 static int 122 test_setup(cryptotest_t *args, test_fg_t *funcs, crypto_op_t **opp) 123 { 124 crypto_op_t *crypto_op = NULL; 125 int ret; 126 127 switch (funcs->tf_fg) { 128 case CRYPTO_FG_DECRYPT: 129 case CRYPTO_FG_ENCRYPT: 130 if (args->key == NULL) 131 return (CRYPTO_FAILED); 132 break; 133 case CRYPTO_FG_MAC: 134 if (args->in == NULL || args->key == NULL) 135 return (CRYPTO_FAILED); 136 break; 137 case CRYPTO_FG_DIGEST: 138 break; 139 default: 140 (void) fprintf(stderr, 141 "Unexpected function group value %" PRIu32 "\n", 142 funcs->tf_fg); 143 abort(); 144 } 145 146 if ((crypto_op = cryptotest_init(args, funcs->tf_fg)) == NULL) { 147 /* cryptotest_init() will prints out a specific error msg */ 148 cryptotest_close(NULL); 149 return (CTEST_INIT_FAILED); 150 } 151 152 if ((ret = get_mech_info(crypto_op)) != CRYPTO_SUCCESS) { 153 cryptotest_close(crypto_op); 154 return (ret); 155 } 156 157 if ((ret = get_hsession_by_mech(crypto_op)) != CRYPTO_SUCCESS) { 158 cryptotest_close(crypto_op); 159 return (ret); 160 } 161 162 *opp = crypto_op; 163 return (CRYPTO_SUCCESS); 164 } 165 166 static int 167 test_multi(cryptotest_t *args, test_fg_t *funcs, uint8_t *cmp, size_t cmplen) 168 { 169 crypto_op_t *crypto_op = NULL; 170 size_t errs = 0; 171 size_t n; 172 int ret; 173 174 (void) fprintf(stderr, "multi-part:\n"); 175 176 if ((ret = test_setup(args, funcs, &crypto_op)) != CRYPTO_SUCCESS) { 177 (void) fprintf(stderr, " fatal error %d\n", ret); 178 exit(EXIT_FAILURE_MULTIPART); 179 } 180 181 for (n = 0; args->updatelens[n] != CTEST_UPDATELEN_END; n++) { 182 char errbuf[BUFSZ] = { 0 }; 183 char sizebuf[BUFSZ] = { 0 }; 184 size_t updatelen = args->updatelens[n]; 185 size_t offset = 0; 186 size_t outlen = 0; 187 188 bzero(args->out, args->outlen); 189 190 if (updatelen == CTEST_UPDATELEN_WHOLE) { 191 updatelen = args->inlen; 192 (void) snprintf(sizebuf, sizeof (sizebuf), 193 "%zu (whole buffer)", updatelen); 194 } else if (updatelen > args->inlen) { 195 /* 196 * This can sometimes cause the same update size to 197 * be used twice if one is specified larger than the 198 * input and one also specifies a test using the 199 * entire input as the update size. It doesn't 200 * hurt anything other than adding a little extra 201 * time. 202 */ 203 updatelen = args->inlen; 204 (void) snprintf(sizebuf, sizeof (sizebuf), 205 "%zu (was %zu but capped at input size)", 206 updatelen, args->updatelens[n]); 207 } else { 208 (void) snprintf(sizebuf, sizeof (sizebuf), "%zu", 209 updatelen); 210 } 211 (void) fprintf(stderr, " update size: %s\n", sizebuf); 212 (void) fflush(stderr); 213 214 if ((ret = funcs->tf_init(crypto_op)) != CRYPTO_SUCCESS) { 215 (void) fprintf(stderr, " fatal error %d\n", ret); 216 exit(EXIT_FAILURE_MULTIPART); 217 } 218 219 while (offset < args->inlen) { 220 size_t len = updatelen; 221 222 if (offset + updatelen > args->inlen) { 223 len = args->inlen - offset; 224 } 225 226 ret = funcs->tf_update(crypto_op, offset, len, &outlen); 227 if (ret != CRYPTO_SUCCESS) { 228 /* 229 * The update functions will print out their 230 * own error messages, so we don't need to. 231 */ 232 errs += 1; 233 break; 234 } 235 236 offset += len; 237 } 238 239 if (ret != CRYPTO_SUCCESS) 240 continue; 241 242 ret = funcs->tf_final(crypto_op, outlen); 243 244 /* 245 * Errors from the crypto frameworks (KCF, PKCS#11) are all 246 * positive (and 0 == success). Negative values are used by 247 * the test framework to signal fatal errors (CTEST_xxx). 248 */ 249 if (ret > 0) { 250 (void) fprintf(stderr, " failure %s\n", 251 cryptotest_errstr(ret, errbuf, sizeof (errbuf))); 252 errs += 1; 253 } else if (ret < 0) { 254 (void) fprintf(stderr, " fatal error %s\n", 255 ctest_errstr(ret, errbuf, sizeof (errbuf))); 256 exit(EXIT_FAILURE_MULTIPART); 257 } else { 258 errs += bufcmp(cmp, args->out, cmplen); 259 } 260 } 261 262 VERIFY3U(errs, <=, INT_MAX); 263 cryptotest_close(crypto_op); 264 return (errs); 265 } 266 267 static int 268 test_single(cryptotest_t *args, test_fg_t *funcs, uint8_t *cmp, size_t cmplen) 269 { 270 crypto_op_t *crypto_op = NULL; 271 char errbuf[BUFSZ] = { 0 }; 272 int ret; 273 274 (void) fprintf(stderr, "single part:\n"); 275 276 if ((ret = test_setup(args, funcs, &crypto_op)) != CRYPTO_SUCCESS) { 277 (void) fprintf(stderr, " fatal error %d\n", ret); 278 exit(EXIT_FAILURE_SINGLEPART); 279 } 280 281 if ((ret = funcs->tf_init(crypto_op)) != CRYPTO_SUCCESS) { 282 (void) fprintf(stderr, " fatal error %d\n", ret); 283 exit(EXIT_FAILURE_SINGLEPART); 284 } 285 286 if ((ret = funcs->tf_single(crypto_op)) != CRYPTO_SUCCESS) 287 goto out; 288 289 /* 290 * Errors from the crypto frameworks (KCF, PKCS#11) are all 291 * positive (and 0 == success). Negative values are used by 292 * the test framework to signal fatal errors (CTEST_xxx). 293 */ 294 if (ret > 0) { 295 (void) fprintf(stderr, " failure %s\n", 296 cryptotest_errstr(ret, errbuf, sizeof (errbuf))); 297 return (1); 298 } else if (ret < 0) { 299 (void) fprintf(stderr, " fatal error %s\n", 300 ctest_errstr(ret, errbuf, sizeof (errbuf))); 301 exit(EXIT_FAILURE_SINGLEPART); 302 } else { 303 ret = bufcmp(cmp, args->out, cmplen); 304 } 305 306 out: 307 (void) cryptotest_close(crypto_op); 308 return ((ret == CRYPTO_SUCCESS) ? 0 : 1); 309 } 310 311 /* 312 * Wrapper functions 313 */ 314 315 int 316 run_test(cryptotest_t *args, uint8_t *cmp, size_t cmplen, 317 test_fg_t *funcs) 318 { 319 size_t errs = 0; 320 static int i = 0; 321 322 (void) fprintf(stderr, "%s: run %d\n", args->mechname, ++i); 323 324 errs += test_multi(args, funcs, cmp, cmplen); 325 326 bzero(args->out, args->outlen); 327 328 errs += test_single(args, funcs, cmp, cmplen); 329 330 VERIFY3U(errs, <=, INT_MAX); 331 return (errs); 332 } 333