1108833Ssam/* $FreeBSD$ */ 2108833Ssam/* 3108833Ssam * The big num stuff is a bit broken at the moment and I've not yet fixed it. 4108833Ssam * The symtom is that odd size big nums will fail. Test code below (it only 5108833Ssam * uses modexp currently). 6108833Ssam * 7108833Ssam * --Jason L. Wright 8108833Ssam */ 9108833Ssam#include <sys/types.h> 10108833Ssam#include <sys/ioctl.h> 11108833Ssam#include <machine/endian.h> 12108833Ssam#include <sys/time.h> 13108833Ssam#include <crypto/cryptodev.h> 14108833Ssam#include <openssl/bn.h> 15167755Ssam 16167755Ssam#include <paths.h> 17108833Ssam#include <fcntl.h> 18108833Ssam#include <err.h> 19108833Ssam#include <string.h> 20108833Ssam#include <unistd.h> 21108833Ssam#include <stdlib.h> 22108833Ssam 23167755Ssamint crid = CRYPTO_FLAG_HARDWARE; 24167755Ssamint verbose = 0; 25108833Ssam 26167755Ssamstatic int 27167755Ssamdevcrypto(void) 28167755Ssam{ 29167755Ssam static int fd = -1; 30167755Ssam 31167755Ssam if (fd < 0) { 32167755Ssam fd = open(_PATH_DEV "crypto", O_RDWR, 0); 33167755Ssam if (fd < 0) 34167755Ssam err(1, _PATH_DEV "crypto"); 35167755Ssam if (fcntl(fd, F_SETFD, 1) == -1) 36167755Ssam err(1, "fcntl(F_SETFD) (devcrypto)"); 37167755Ssam } 38167755Ssam return fd; 39167755Ssam} 40167755Ssam 41167755Ssamstatic int 42167755Ssamcrlookup(const char *devname) 43167755Ssam{ 44167755Ssam struct crypt_find_op find; 45167755Ssam 46167755Ssam find.crid = -1; 47167755Ssam strlcpy(find.name, devname, sizeof(find.name)); 48167755Ssam if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) 49167755Ssam err(1, "ioctl(CIOCFINDDEV)"); 50167755Ssam return find.crid; 51167755Ssam} 52167755Ssam 53167755Ssamstatic const char * 54167755Ssamcrfind(int crid) 55167755Ssam{ 56167755Ssam static struct crypt_find_op find; 57167755Ssam 58167755Ssam bzero(&find, sizeof(find)); 59167755Ssam find.crid = crid; 60167755Ssam if (ioctl(devcrypto(), CIOCFINDDEV, &find) == -1) 61167755Ssam err(1, "ioctl(CIOCFINDDEV)"); 62167755Ssam return find.name; 63167755Ssam} 64167755Ssam 65108833Ssam/* 66108833Ssam * Convert a little endian byte string in 'p' that 67108833Ssam * is 'plen' bytes long to a BIGNUM. If 'dst' is NULL, 68108833Ssam * a new BIGNUM is allocated. Returns NULL on failure. 69108833Ssam * 70108833Ssam * XXX there has got to be a more efficient way to do 71108833Ssam * this, but I haven't figured out enough of the OpenSSL 72108833Ssam * magic. 73108833Ssam */ 74108833SsamBIGNUM * 75108833Ssamle_to_bignum(BIGNUM *dst, u_int8_t *p, int plen) 76108833Ssam{ 77108833Ssam u_int8_t *pd; 78108833Ssam int i; 79108833Ssam 80108833Ssam if (plen == 0) 81108833Ssam return (NULL); 82108833Ssam 83108833Ssam if ((pd = (u_int8_t *)malloc(plen)) == NULL) 84108833Ssam return (NULL); 85108833Ssam 86108833Ssam for (i = 0; i < plen; i++) 87108833Ssam pd[i] = p[plen - i - 1]; 88108833Ssam 89108833Ssam dst = BN_bin2bn(pd, plen, dst); 90108833Ssam free(pd); 91108833Ssam return (dst); 92108833Ssam} 93108833Ssam 94108833Ssam/* 95108833Ssam * Convert a BIGNUM to a little endian byte string. 96108833Ssam * If 'rd' is NULL, allocate space for it, otherwise 97108833Ssam * 'rd' is assumed to have room for BN_num_bytes(n) 98108833Ssam * bytes. Returns NULL on failure. 99108833Ssam */ 100108833Ssamu_int8_t * 101108833Ssambignum_to_le(BIGNUM *n, u_int8_t *rd) 102108833Ssam{ 103108833Ssam int i, j, k; 104108833Ssam int blen = BN_num_bytes(n); 105108833Ssam 106108833Ssam if (blen == 0) 107108833Ssam return (NULL); 108108833Ssam if (rd == NULL) 109108833Ssam rd = (u_int8_t *)malloc(blen); 110108833Ssam if (rd == NULL) 111108833Ssam return (NULL); 112108833Ssam 113108833Ssam for (i = 0, j = 0; i < n->top; i++) { 114108833Ssam for (k = 0; k < BN_BITS2 / 8; k++) { 115108833Ssam if ((j + k) >= blen) 116108833Ssam goto out; 117108833Ssam rd[j + k] = n->d[i] >> (k * 8); 118108833Ssam } 119108833Ssam j += BN_BITS2 / 8; 120108833Ssam } 121108833Ssamout: 122108833Ssam return (rd); 123108833Ssam} 124108833Ssam 125108833Ssamint 126108833SsamUB_mod_exp(BIGNUM *res, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx) 127108833Ssam{ 128108833Ssam struct crypt_kop kop; 129108833Ssam u_int8_t *ale, *ble, *cle; 130167755Ssam static int crypto_fd = -1; 131108833Ssam 132167755Ssam if (crypto_fd == -1 && ioctl(devcrypto(), CRIOGET, &crypto_fd) == -1) 133167755Ssam err(1, "CRIOGET"); 134108833Ssam 135108833Ssam if ((ale = bignum_to_le(a, NULL)) == NULL) 136108833Ssam err(1, "bignum_to_le, a"); 137108833Ssam if ((ble = bignum_to_le(b, NULL)) == NULL) 138108833Ssam err(1, "bignum_to_le, b"); 139108833Ssam if ((cle = bignum_to_le(c, NULL)) == NULL) 140108833Ssam err(1, "bignum_to_le, c"); 141108833Ssam 142108833Ssam bzero(&kop, sizeof(kop)); 143108833Ssam kop.crk_op = CRK_MOD_EXP; 144108833Ssam kop.crk_iparams = 3; 145108833Ssam kop.crk_oparams = 1; 146167755Ssam kop.crk_crid = crid; 147108833Ssam kop.crk_param[0].crp_p = ale; 148108833Ssam kop.crk_param[0].crp_nbits = BN_num_bytes(a) * 8; 149108833Ssam kop.crk_param[1].crp_p = ble; 150108833Ssam kop.crk_param[1].crp_nbits = BN_num_bytes(b) * 8; 151108833Ssam kop.crk_param[2].crp_p = cle; 152108833Ssam kop.crk_param[2].crp_nbits = BN_num_bytes(c) * 8; 153108833Ssam kop.crk_param[3].crp_p = cle; 154108833Ssam kop.crk_param[3].crp_nbits = BN_num_bytes(c) * 8; 155108833Ssam 156167755Ssam if (ioctl(crypto_fd, CIOCKEY2, &kop) == -1) 157167755Ssam err(1, "CIOCKEY2"); 158167755Ssam if (verbose) 159167755Ssam printf("device = %s\n", crfind(kop.crk_crid)); 160108833Ssam 161108833Ssam bzero(ale, BN_num_bytes(a)); 162108833Ssam free(ale); 163108833Ssam bzero(ble, BN_num_bytes(b)); 164108833Ssam free(ble); 165108833Ssam 166108833Ssam if (kop.crk_status != 0) { 167108833Ssam printf("error %d\n", kop.crk_status); 168108833Ssam bzero(cle, BN_num_bytes(c)); 169108833Ssam free(cle); 170108833Ssam return (-1); 171108833Ssam } else { 172108833Ssam res = le_to_bignum(res, cle, BN_num_bytes(c)); 173108833Ssam bzero(cle, BN_num_bytes(c)); 174108833Ssam free(cle); 175108833Ssam if (res == NULL) 176108833Ssam err(1, "le_to_bignum"); 177108833Ssam return (0); 178108833Ssam } 179108833Ssam return (0); 180108833Ssam} 181108833Ssam 182108833Ssamvoid 183108833Ssamshow_result(a, b, c, sw, hw) 184108833SsamBIGNUM *a, *b, *c, *sw, *hw; 185108833Ssam{ 186108833Ssam printf("\n"); 187108833Ssam 188108833Ssam printf("A = "); 189108833Ssam BN_print_fp(stdout, a); 190108833Ssam printf("\n"); 191108833Ssam 192108833Ssam printf("B = "); 193108833Ssam BN_print_fp(stdout, b); 194108833Ssam printf("\n"); 195108833Ssam 196108833Ssam printf("C = "); 197108833Ssam BN_print_fp(stdout, c); 198108833Ssam printf("\n"); 199108833Ssam 200108833Ssam printf("sw= "); 201108833Ssam BN_print_fp(stdout, sw); 202108833Ssam printf("\n"); 203108833Ssam 204108833Ssam printf("hw= "); 205108833Ssam BN_print_fp(stdout, hw); 206108833Ssam printf("\n"); 207108833Ssam 208108833Ssam printf("\n"); 209108833Ssam} 210108833Ssam 211108833Ssamvoid 212108833Ssamtestit(void) 213108833Ssam{ 214108833Ssam BIGNUM *a, *b, *c, *r1, *r2; 215108833Ssam BN_CTX *ctx; 216108833Ssam 217108833Ssam ctx = BN_CTX_new(); 218108833Ssam 219108833Ssam a = BN_new(); 220108833Ssam b = BN_new(); 221108833Ssam c = BN_new(); 222108833Ssam r1 = BN_new(); 223108833Ssam r2 = BN_new(); 224108833Ssam 225108833Ssam BN_pseudo_rand(a, 1023, 0, 0); 226108833Ssam BN_pseudo_rand(b, 1023, 0, 0); 227108833Ssam BN_pseudo_rand(c, 1024, 0, 0); 228108833Ssam 229108833Ssam if (BN_cmp(a, c) > 0) { 230108833Ssam BIGNUM *rem = BN_new(); 231108833Ssam 232108833Ssam BN_mod(rem, a, c, ctx); 233108833Ssam UB_mod_exp(r2, rem, b, c, ctx); 234108833Ssam BN_free(rem); 235108833Ssam } else { 236108833Ssam UB_mod_exp(r2, a, b, c, ctx); 237108833Ssam } 238108833Ssam BN_mod_exp(r1, a, b, c, ctx); 239108833Ssam 240108833Ssam if (BN_cmp(r1, r2) != 0) { 241108833Ssam show_result(a, b, c, r1, r2); 242108833Ssam } 243108833Ssam 244108833Ssam BN_free(r2); 245108833Ssam BN_free(r1); 246108833Ssam BN_free(c); 247108833Ssam BN_free(b); 248108833Ssam BN_free(a); 249108833Ssam BN_CTX_free(ctx); 250108833Ssam} 251108833Ssam 252167755Ssamstatic void 253167755Ssamusage(const char* cmd) 254167755Ssam{ 255167755Ssam printf("usage: %s [-d dev] [-v] [count]\n", cmd); 256167755Ssam printf("count is the number of bignum ops to do\n"); 257167755Ssam printf("\n"); 258167755Ssam printf("-d use specific device\n"); 259167755Ssam printf("-v be verbose\n"); 260167755Ssam exit(-1); 261167755Ssam} 262167755Ssam 263108833Ssamint 264167755Ssammain(int argc, char *argv[]) 265108833Ssam{ 266167755Ssam int c, i; 267108833Ssam 268167755Ssam while ((c = getopt(argc, argv, "d:v")) != -1) { 269167755Ssam switch (c) { 270167755Ssam case 'd': 271167755Ssam crid = crlookup(optarg); 272167755Ssam break; 273167755Ssam case 'v': 274167755Ssam verbose = 1; 275167755Ssam break; 276167755Ssam default: 277167755Ssam usage(argv[0]); 278167755Ssam } 279167755Ssam } 280167755Ssam argc -= optind, argv += optind; 281167755Ssam 282108833Ssam for (i = 0; i < 1000; i++) { 283108833Ssam fprintf(stderr, "test %d\n", i); 284108833Ssam testit(); 285108833Ssam } 286108833Ssam return (0); 287108833Ssam} 288