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