static int do_random(int argc, char **argv) { unsigned char buffer[128]; int r, count; if (argc != 1) goto usage; count = atoi(argv[0]); if (count < 0 || count > 128) { printf("Number must be in range 0..128\n"); return -1; } r = sc_get_challenge(card, buffer, count); if (r < 0) { printf("Failed to get random bytes: %s\n", sc_strerror(r)); return -1; } util_hex_dump_asc(stdout, buffer, count, 0); return 0; usage: printf("Usage: random count\n"); return -1; }
static void do_random() { unsigned char buffer[128]; int r, count = 128; int n = 128; int n_bits = 1024; struct rand_pool_info *output; int fd = open(DEV_RANDOM, O_WRONLY); if (fd == -1) { syslog(LOG_ERR,"Failed to open %s", DEV_RANDOM); } while (1) { r = sc_get_challenge(card, buffer, count); if (r < 0) { syslog(LOG_ERR,"Failed to get random bytes: %s\n", sc_strerror(r)); } output = (struct rand_pool_info *)malloc(sizeof(struct rand_pool_info) + n); output -> entropy_count = n_bits; output -> buf_size = n; memcpy(&(output -> buf[0]), buffer, n); if (ioctl(fd, RNDADDENTROPY, output) == -1) { syslog(LOG_ERR,"ioctl(RNDADDENTROPY) failed!"); } free(output); sleep(1); } close(fd); }
int main(int argc, char *argv[]) { struct timeval tv1, tv2; int i, c, cnt = 3, freq[256]; u8 buf[8]; i = sc_test_init(&argc, argv); if (i < 0) return 1; for (i = 0; i < 256; i++) freq[i] = 0; c = 0; while (cnt) { if ((c % 10) == 1) { printf("."); fflush(stdout); } if (c == 0) gettimeofday(&tv1, NULL); i = sc_get_challenge(card, buf, 8); if (i != 0) { fprintf(stderr, "sc_get_challenge() failed: %s\n", sc_strerror(i)); sc_test_cleanup(); return 1; } for (i = 0; i < 8; i++) freq[buf[i]]++; c++; if (c == 100) { unsigned long long foo, foo2; gettimeofday(&tv2, NULL); foo = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; foo2 = tv1.tv_sec * 1000 + tv1.tv_usec / 1000; printf("\nTime to generate 64 bits of randomness: %lld ms\n", (foo - foo2) / 100); printf("Frequencies:\n"); for (i = 0; i < 256; i++) { if (i && (i & 0x07) == 0) printf("\n"); printf("%02X: %3d ", i, freq[i]); } printf("\n"); c = 0; cnt--; } } sc_test_cleanup(); return 0; }
static int gostchiper(sc_card_t *card, u8 keyid, const char *path_infile, const char *path_outfile, const char IV[IV_SIZE], int is_iv, int op_oper) { int r; u8 iv[IV_SIZE]; if (op_oper == OP_ENCRYPT) { if (!is_iv) { /* generated random on token */ r = sc_get_challenge(card, iv, IV_SIZE); if (r) { fprintf(stderr, "Error: Generate IV" " (get challenge) failed: %s\n", sc_strerror(r)); return -1; } } else memcpy(iv, IV, IV_SIZE); } return do_crypt(card, keyid, path_infile, path_outfile, iv, op_oper); }
static void create_dkek_share(sc_card_t *card, const char *outf, int iter, char *password, int password_shares_threshold, int password_shares_total) { EVP_CIPHER_CTX ctx; FILE *out = NULL; u8 filebuff[64], key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH],outbuff[64]; u8 dkek_share[32]; char *pwd = NULL; int r = 0, outlen, pwdlen = 0; if (password == NULL) { if (password_shares_threshold == -1) { ask_for_password(&pwd, &pwdlen); } else { // create password using threshold scheme r = generate_pwd_shares(card, &pwd, &pwdlen, password_shares_threshold, password_shares_total); } } else { pwd = password; pwdlen = strlen(password); } if (r < 0) { printf("Creating DKEK share failed"); return; } memcpy(filebuff, magic, sizeof(magic) - 1); r = sc_get_challenge(card, filebuff + 8, 8); if (r < 0) { printf("Error generating random number failed with ", sc_strerror(r)); return; } printf("Enciphering DKEK share, please wait...\n"); EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), filebuff + 8, (u8 *)pwd, pwdlen, iter, key, iv); if (password == NULL) { OPENSSL_cleanse(pwd, pwdlen); free(pwd); } r = sc_get_challenge(card, dkek_share, sizeof(dkek_share)); if (r < 0) { printf("Error generating random number failed with ", sc_strerror(r)); return; } EVP_CIPHER_CTX_init(&ctx); EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv); if (!EVP_EncryptUpdate(&ctx, filebuff + 16, &outlen, dkek_share, sizeof(dkek_share))) { printf("Error encrypting DKEK share\n"); return; } if (!EVP_EncryptFinal_ex(&ctx, filebuff + 16 + outlen, &r)) { printf("Error encrypting DKEK share\n"); return; } out = fopen(outf, "wb"); if (out == NULL) { perror(outf); return; } if (fwrite(filebuff, 1, sizeof(filebuff), out) != sizeof(filebuff)) { perror(outf); return; } fclose(out); OPENSSL_cleanse(filebuff, sizeof(filebuff)); EVP_CIPHER_CTX_cleanup(&ctx); printf("DKEK share created and saved to %s\n", outf); }
static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, int password_shares_total) { int r, i; BIGNUM prime; BIGNUM secret; char buf[64]; char hex[64]; int l; secret_share_t *shares = NULL; secret_share_t *sp; u8 rngseed[16]; printf( "\nThe DKEK will be enciphered using a randomly generated 64 bit password.\n"); printf( "This password is split using a (%i-of-%i) threshold scheme.\n\n", password_shares_threshold, password_shares_total); printf( "Please keep the generated and encrypted DKEK file in a safe location. We also recommend \n"); printf( "to keep a paper printout, in case the electronic version becomes unavailable. A printable version\n"); printf( "of the file can be generated using \"openssl base64 -in <filename>\".\n"); printf("\n\nPress <enter> to continue"); waitForEnterKeyPressed(); *pwd = calloc(1, 8); *pwdlen = 8; r = sc_get_challenge(card, *pwd, 8); if (r < 0) { printf("Error generating random key failed with ", sc_strerror(r)); OPENSSL_cleanse(pwd, *pwdlen); free(pwd); return r; } **pwd |= 0x80; /* * Initialize prime and secret */ BN_init(&prime); BN_init(&secret); /* * Encode the secret value */ BN_bin2bn(*pwd, *pwdlen, &secret); /* * Generate seed and calculate a prime depending on the size of the secret */ r = sc_get_challenge(card, rngseed, 16); if (r < 0) { printf("Error generating random seed failed with ", sc_strerror(r)); OPENSSL_cleanse(pwd, *pwdlen); free(pwd); return r; } generatePrime(&prime, &secret, password_shares_total, rngseed); // Allocate data buffer for the generated shares shares = malloc(password_shares_total * sizeof(secret_share_t)); createShares(&secret, password_shares_threshold, password_shares_total, prime, shares); sp = shares; for (i = 0; i < password_shares_total; i++) { clearScreen(); printf("Press <enter> to display key share %i of %i\n\n", i + 1, password_shares_total); waitForEnterKeyPressed(); clearScreen(); printf("Share %i of %i\n\n", i + 1, password_shares_total); l = BN_bn2bin(&prime, buf); sc_bin_to_hex(buf, l, hex, 64, ':'); printf("\nPrime : %s\n", hex); printf("Share ID : %s\n", BN_bn2dec(&(sp->x))); l = BN_bn2bin(&(sp->y), buf); sc_bin_to_hex(buf, l, hex, 64, ':'); printf("Share value : %s\n", hex); printf("\n\nPlease note ALL values above and press <enter> when finished"); waitForEnterKeyPressed(); sp++; } clearScreen(); cleanUpShares(shares, password_shares_total); BN_clear_free(&prime); BN_clear_free(&secret); return 0; }
int iasecc_sm_external_authentication(struct sc_card *card, unsigned skey_ref, int *tries_left) { struct sc_context *ctx = card->ctx; #ifdef ENABLE_SM struct sm_info *sm_info = &card->sm_ctx.info; struct sm_cwa_session *cwa_session = &sm_info->session.cwa; struct sc_remote_data rdata; struct sc_apdu apdu; unsigned char sbuf[0x100]; int rv, offs; LOG_FUNC_CALLED(ctx); sc_log(ctx, "iasecc_sm_external_authentication(): SKey ref %i", skey_ref); if (card->sm_ctx.sm_mode == SM_MODE_NONE) LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Cannot do 'External Authentication' without SM activated "); strncpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section)); sm_info->cmd = SM_CMD_EXTERNAL_AUTH; sm_info->serialnr = card->serialnr; sm_info->card_type = card->type; sm_info->sm_type = SM_TYPE_CWA14890; cwa_session->params.crt_at.usage = IASECC_UQB_AT_EXTERNAL_AUTHENTICATION; cwa_session->params.crt_at.algo = IASECC_ALGORITHM_ROLE_AUTH; cwa_session->params.crt_at.refs[0] = skey_ref; offs = 0; sbuf[offs++] = IASECC_CRT_TAG_ALGO; sbuf[offs++] = 0x01; sbuf[offs++] = IASECC_ALGORITHM_ROLE_AUTH; sbuf[offs++] = IASECC_CRT_TAG_REFERENCE; sbuf[offs++] = 0x01; sbuf[offs++] = skey_ref; sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x81, 0xA4); apdu.data = sbuf; apdu.datalen = offs; apdu.lc = offs; rv = sc_transmit_apdu(card, &apdu); LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): APDU transmit failed"); rv = sc_check_sw(card, apdu.sw1, apdu.sw2); LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): set SE error"); rv = sc_get_challenge(card, cwa_session->card_challenge, sizeof(cwa_session->card_challenge)); LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): set SE error"); sc_remote_data_init(&rdata); if (!card->sm_ctx.module.ops.initialize) LOG_TEST_RET(ctx, SC_ERROR_SM_NOT_INITIALIZED, "No SM module"); rv = card->sm_ctx.module.ops.initialize(ctx, sm_info, &rdata); LOG_TEST_RET(ctx, rv, "SM: INITIALIZE failed"); sc_log(ctx, "sm_iasecc_external_authentication(): rdata length %i\n", rdata.length); rv = iasecc_sm_transmit_apdus (card, &rdata, NULL, 0); if (rv == SC_ERROR_PIN_CODE_INCORRECT && tries_left) *tries_left = (rdata.data + rdata.length - 1)->apdu.sw2 & 0x0F; LOG_TEST_RET(ctx, rv, "sm_iasecc_external_authentication(): execute failed"); LOG_FUNC_RETURN(ctx, rv); #else LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of SM and External Authentication"); return SC_ERROR_NOT_SUPPORTED; #endif }
int main(int argc, char *argv[]) { int i, c, r, cnt = 3, freq[39]; struct timeval tv1, tv2; u8 buf[14]; i = sc_test_init(&argc, argv); for (i = 0; i < 39; i++) freq[i] = 0; c = 0; while (cnt) { u8 nbuf[39]; for (i = 0; i < 39; i++) { nbuf[i] = i + 1; } if (c == 0) gettimeofday(&tv1, NULL); sc_lock(card); r = sc_get_challenge(card, buf, 14); sc_unlock(card); if (r == 0) { int left = 39; printf("Lottery: "); for (i = 0; i < 7; i++) { unsigned short s = buf[2 * i] + (buf[2 * i + 1] << 8); int lot = s % (left + 1); int num = nbuf[lot]; nbuf[lot] = nbuf[left - 1]; left--; freq[num - 1]++; printf("%3d ", num); } printf("\n"); } else { fprintf(stderr, "sc_get_challenge() failed: %s\n", sc_strerror(r)); sc_test_cleanup(); return 1; } c++; if (c == 50) { unsigned long long foo, foo2; gettimeofday(&tv2, NULL); foo = tv2.tv_sec * 1000 + tv2.tv_usec / 1000; foo2 = tv1.tv_sec * 1000 + tv1.tv_usec / 1000; printf("Time per one: %lld ms\n", (foo - foo2) / 50); printf("Frequencies:\n"); for (i = 0; i < 39; i++) { printf("%3d: %-5d", i + 1, freq[i]); if (((i + 1) % 10) == 0) printf("\n"); } printf("\n"); c = 0; cnt--; } } sc_test_cleanup(); return 0; }
static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, int password_shares_total) { int r, i; BIGNUM *prime; BIGNUM *secret; unsigned char buf[64]; char hex[64]; int l; secret_share_t *shares = NULL; secret_share_t *sp; u8 rngseed[16]; if ((password_shares_threshold == -1) || (password_shares_total == -1)) { fprintf(stderr, "Must specify both, --pwd-shares-total and --pwd-shares-threshold\n"); return -1; } if (password_shares_total < 3) { fprintf(stderr, "--pwd-shares-total must be 3 or larger\n"); return -1; } if (password_shares_threshold < 2) { fprintf(stderr, "--pwd-shares-threshold must 2 or larger\n"); return -1; } if (password_shares_threshold > password_shares_total) { fprintf(stderr, "--pwd-shares-threshold must be smaller or equal to --pwd-shares-total\n"); return -1; } printf( "\nThe DKEK will be enciphered using a randomly generated 64 bit password.\n"); printf( "This password is split using a (%i-of-%i) threshold scheme.\n\n", password_shares_threshold, password_shares_total); printf( "Please keep the generated and encrypted DKEK file in a safe location. We also recommend \n"); printf( "to keep a paper printout, in case the electronic version becomes unavailable. A printable version\n"); printf( "of the file can be generated using \"openssl base64 -in <filename>\".\n"); printf("\n\nPress <enter> to continue"); waitForEnterKeyPressed(); *pwd = calloc(1, 8); *pwdlen = 8; r = sc_get_challenge(card, (unsigned char *)*pwd, 8); if (r < 0) { printf("Error generating random key failed with %s", sc_strerror(r)); OPENSSL_cleanse(*pwd, *pwdlen); free(*pwd); return r; } **pwd &= 0x7F; // Make sure the bit size of the secret is not bigger than 63 bits /* * Initialize prime and secret */ prime = BN_new(); secret = BN_new(); /* * Encode the secret value */ BN_bin2bn((unsigned char *)*pwd, *pwdlen, secret); /* * Generate seed and calculate a prime depending on the size of the secret */ r = sc_get_challenge(card, rngseed, SEED_LENGTH); if (r < 0) { printf("Error generating random seed failed with %s", sc_strerror(r)); OPENSSL_cleanse(*pwd, *pwdlen); free(*pwd); return r; } r = generatePrime(prime, secret, 64, rngseed, SEED_LENGTH); if (r < 0) { printf("Error generating valid prime number. Please try again."); OPENSSL_cleanse(*pwd, *pwdlen); free(*pwd); return r; } // Allocate data buffer for the generated shares shares = malloc(password_shares_total * sizeof(secret_share_t)); createShares(secret, password_shares_threshold, password_shares_total, prime, shares); sp = shares; for (i = 0; i < password_shares_total; i++) { clearScreen(); printf("Press <enter> to display key share %i of %i\n\n", i + 1, password_shares_total); waitForEnterKeyPressed(); clearScreen(); printf("Share %i of %i\n\n", i + 1, password_shares_total); l = BN_bn2bin(prime, buf); sc_bin_to_hex(buf, l, hex, 64, ':'); printf("\nPrime : %s\n", hex); printf("Share ID : %s\n", BN_bn2dec((sp->x))); l = BN_bn2bin((sp->y), buf); sc_bin_to_hex(buf, l, hex, 64, ':'); printf("Share value : %s\n", hex); printf("\n\nPlease note ALL values above and press <enter> when finished"); waitForEnterKeyPressed(); sp++; } clearScreen(); cleanUpShares(shares, password_shares_total); BN_clear_free(prime); BN_clear_free(secret); return 0; }