1/* $FreeBSD$ */ 2/* 3 * The big num stuff is a bit broken at the moment and I've not yet fixed it. 4 * The symtom is that odd size big nums will fail. Test code below (it only 5 * uses modexp currently). 6 * 7 * --Jason L. Wright 8 */ 9#include <sys/types.h> 10#include <sys/endian.h> 11#include <sys/ioctl.h> 12#include <sys/time.h> 13#include <crypto/cryptodev.h> 14 15#include <err.h> 16#include <fcntl.h> 17#include <paths.h> 18#include <stdlib.h> 19#include <string.h> 20#include <unistd.h> 21 22#include <openssl/bn.h> 23#include <openssl/err.h> 24 25int crid = CRYPTO_FLAG_HARDWARE; 26int verbose = 0; 27 28static int 29devcrypto(void) 30{ 31 static int fd = -1; 32 33 if (fd < 0) { 34 fd = open(_PATH_DEV "crypto", O_RDWR, 0); 35 if (fd < 0) 36 err(1, _PATH_DEV "crypto"); 37 if (fcntl(fd, F_SETFD, 1) == -1) 38 err(1, "fcntl(F_SETFD) (devcrypto)"); 39 } 40 return fd; 41} 42 43static int 44crlookup(const char *devname) 45{ 46 struct crypt_find_op find; 47 48 find.crid = -1; 49 strlcpy(find.name, devname, sizeof(find.name)); 50 if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) 51 err(1, "ioctl(CIOCFINDDEV)"); 52 return find.crid; 53} 54 55static const char * 56crfind(int crid) 57{ 58 static struct crypt_find_op find; 59 60 bzero(&find, sizeof(find)); 61 find.crid = crid; 62 if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) 63 err(1, "ioctl(CIOCFINDDEV)"); 64 return find.name; 65} 66 67/* 68 * Convert a little endian byte string in 'p' that is 'plen' bytes long to a 69 * BIGNUM. A new BIGNUM is allocated. Returns NULL on failure. 70 */ 71static BIGNUM * 72le_to_bignum(BIGNUM *res, const void *p, int plen) 73{ 74 75 res = BN_lebin2bn(p, plen, res); 76 if (res == NULL) 77 ERR_print_errors_fp(stderr); 78 79 return (res); 80} 81 82/* 83 * Convert a BIGNUM to a little endian byte string. Space for BN_num_bytes(n) 84 * is allocated. 85 * Returns NULL on failure. 86 */ 87static void * 88bignum_to_le(const BIGNUM *n) 89{ 90 int blen, error; 91 void *rd; 92 93 blen = BN_num_bytes(n); 94 if (blen == 0) 95 return (NULL); 96 97 rd = malloc(blen); 98 if (rd == NULL) 99 return (NULL); 100 101 error = BN_bn2lebinpad(n, rd, blen); 102 if (error < 0) { 103 ERR_print_errors_fp(stderr); 104 free(rd); 105 return (NULL); 106 } 107 108 return (rd); 109} 110 111static int 112UB_mod_exp(BIGNUM *res, const BIGNUM *a, const BIGNUM *b, const BIGNUM *c) 113{ 114 struct crypt_kop kop; 115 void *ale, *ble, *cle; 116 static int crypto_fd = -1; 117 118 if (crypto_fd == -1 && ioctl(devcrypto(), CRIOGET, &crypto_fd) == -1) 119 err(1, "CRIOGET"); 120 121 if ((ale = bignum_to_le(a)) == NULL) 122 err(1, "bignum_to_le, a"); 123 if ((ble = bignum_to_le(b)) == NULL) 124 err(1, "bignum_to_le, b"); 125 if ((cle = bignum_to_le(c)) == NULL) 126 err(1, "bignum_to_le, c"); 127 128 bzero(&kop, sizeof(kop)); 129 kop.crk_op = CRK_MOD_EXP; 130 kop.crk_iparams = 3; 131 kop.crk_oparams = 1; 132 kop.crk_crid = crid; 133 kop.crk_param[0].crp_p = ale; 134 kop.crk_param[0].crp_nbits = BN_num_bytes(a) * 8; 135 kop.crk_param[1].crp_p = ble; 136 kop.crk_param[1].crp_nbits = BN_num_bytes(b) * 8; 137 kop.crk_param[2].crp_p = cle; 138 kop.crk_param[2].crp_nbits = BN_num_bytes(c) * 8; 139 kop.crk_param[3].crp_p = cle; 140 kop.crk_param[3].crp_nbits = BN_num_bytes(c) * 8; 141 142 if (ioctl(crypto_fd, CIOCKEY2, &kop) == -1) 143 err(1, "CIOCKEY2"); 144 if (verbose) 145 printf("device = %s\n", crfind(kop.crk_crid)); 146 147 explicit_bzero(ale, BN_num_bytes(a)); 148 free(ale); 149 explicit_bzero(ble, BN_num_bytes(b)); 150 free(ble); 151 152 if (kop.crk_status != 0) { 153 printf("error %d\n", kop.crk_status); 154 explicit_bzero(cle, BN_num_bytes(c)); 155 free(cle); 156 return (-1); 157 } else { 158 res = le_to_bignum(res, cle, BN_num_bytes(c)); 159 explicit_bzero(cle, BN_num_bytes(c)); 160 free(cle); 161 if (res == NULL) 162 err(1, "le_to_bignum"); 163 return (0); 164 } 165 return (0); 166} 167 168static void 169show_result(const BIGNUM *a, const BIGNUM *b, const BIGNUM *c, 170 const BIGNUM *sw, const BIGNUM *hw) 171{ 172 printf("\n"); 173 174 printf("A = "); 175 BN_print_fp(stdout, a); 176 printf("\n"); 177 178 printf("B = "); 179 BN_print_fp(stdout, b); 180 printf("\n"); 181 182 printf("C = "); 183 BN_print_fp(stdout, c); 184 printf("\n"); 185 186 printf("sw= "); 187 BN_print_fp(stdout, sw); 188 printf("\n"); 189 190 printf("hw= "); 191 BN_print_fp(stdout, hw); 192 printf("\n"); 193 194 printf("\n"); 195} 196 197static void 198testit(void) 199{ 200 BIGNUM *a, *b, *c, *r1, *r2; 201 BN_CTX *ctx; 202 203 ctx = BN_CTX_new(); 204 205 a = BN_new(); 206 b = BN_new(); 207 c = BN_new(); 208 r1 = BN_new(); 209 r2 = BN_new(); 210 211 BN_pseudo_rand(a, 1023, 0, 0); 212 BN_pseudo_rand(b, 1023, 0, 0); 213 BN_pseudo_rand(c, 1024, 0, 0); 214 215 if (BN_cmp(a, c) > 0) { 216 BIGNUM *rem = BN_new(); 217 218 BN_mod(rem, a, c, ctx); 219 UB_mod_exp(r2, rem, b, c); 220 BN_free(rem); 221 } else { 222 UB_mod_exp(r2, a, b, c); 223 } 224 BN_mod_exp(r1, a, b, c, ctx); 225 226 if (BN_cmp(r1, r2) != 0) { 227 show_result(a, b, c, r1, r2); 228 } 229 230 BN_free(r2); 231 BN_free(r1); 232 BN_free(c); 233 BN_free(b); 234 BN_free(a); 235 BN_CTX_free(ctx); 236} 237 238static void 239usage(const char* cmd) 240{ 241 printf("usage: %s [-d dev] [-v] [count]\n", cmd); 242 printf("count is the number of bignum ops to do\n"); 243 printf("\n"); 244 printf("-d use specific device\n"); 245 printf("-v be verbose\n"); 246 exit(-1); 247} 248 249int 250main(int argc, char *argv[]) 251{ 252 int c, i; 253 254 while ((c = getopt(argc, argv, "d:v")) != -1) { 255 switch (c) { 256 case 'd': 257 crid = crlookup(optarg); 258 break; 259 case 'v': 260 verbose = 1; 261 break; 262 default: 263 usage(argv[0]); 264 } 265 } 266 argc -= optind, argv += optind; 267 268 for (i = 0; i < 1000; i++) { 269 fprintf(stderr, "test %d\n", i); 270 testit(); 271 } 272 return (0); 273} 274