int write_chalresp_state(FILE *f, CR_STATE *state) { char challenge_hex[CR_CHALLENGE_SIZE * 2 + 1], response_hex[CR_RESPONSE_SIZE * 2 + 1]; char salt_hex[CR_SALT_SIZE * 2 + 1], hashed_hex[CR_RESPONSE_SIZE * 2 + 1]; unsigned char salt[CR_SALT_SIZE], hash[CR_RESPONSE_SIZE]; YK_PRF_METHOD prf_method = {20, yk_hmac_sha1}; unsigned int iterations = CR_DEFAULT_ITERATIONS; int fd; memset(challenge_hex, 0, sizeof(challenge_hex)); memset(response_hex, 0, sizeof(response_hex)); memset(salt_hex, 0, sizeof(salt_hex)); memset(hashed_hex, 0, sizeof(hashed_hex)); yubikey_hex_encode(challenge_hex, (char *)state->challenge, state->challenge_len); yubikey_hex_encode(response_hex, (char *)state->response, state->response_len); if(state->iterations > 0) { iterations = state->iterations; } generate_random(salt, CR_SALT_SIZE); yk_pbkdf2(response_hex, salt, CR_SALT_SIZE, iterations, hash, CR_RESPONSE_SIZE, &prf_method); yubikey_hex_encode(hashed_hex, (char *)hash, CR_RESPONSE_SIZE); yubikey_hex_encode(salt_hex, (char *)salt, CR_SALT_SIZE); rewind(f); fd = fileno(f); if (fd == -1) goto out; if (ftruncate(fd, 0)) goto out; fprintf(f, "v2:%s:%s:%s:%u:%d\n", challenge_hex, hashed_hex, salt_hex, iterations, state->slot); if (fflush(f) < 0) goto out; if (fsync(fd) < 0) goto out; return 1; out: return 0; }
/* Generate an AES (128 bits) or HMAC (despite the function name) (160 bits) * key from user entered input. * * Use user provided salt, or use salt from an available random device. * If no random device is available we fall back to using 2048 bits of * system time data, together with the user input, as salt. */ int ykp_AES_key_from_passphrase(YKP_CONFIG *cfg, const char *passphrase, const char *salt) { if (cfg) { char *random_places[] = { "/dev/srandom", "/dev/urandom", "/dev/random", 0 }; char **random_place; uint8_t _salt[8]; size_t _salt_len = 0; unsigned char buf[sizeof(cfg->ykcore_config.key) + 4]; int rc; int key_bytes = _get_supported_key_length(cfg); assert (key_bytes <= sizeof(buf)); if (salt) { _salt_len = strlen(salt); if (_salt_len > 8) _salt_len = 8; memcpy(_salt, salt, _salt_len); } else { for (random_place = random_places; *random_place; random_place++) { FILE *random_file = fopen(*random_place, "r"); if (random_file) { size_t read_bytes = 0; while (read_bytes < sizeof(_salt)) { size_t n = fread(&_salt[read_bytes], 1, sizeof (_salt) - read_bytes, random_file); read_bytes += n; } fclose(random_file); _salt_len = sizeof(_salt); break; /* from for loop */ } } } if (_salt_len == 0) { /* There was no randomness files, so create a cheap salt from time */ # include <ykpbkdf2.h> time_t t = time(NULL); uint8_t output[256]; /* 2048 bits is a lot! */ yk_hmac_sha1.prf_fn(passphrase, strlen(passphrase), (char *)&t, sizeof(t), output, sizeof(output)); memcpy(_salt, output, sizeof(_salt)); _salt_len = sizeof(_salt); } rc = yk_pbkdf2(passphrase, _salt, _salt_len, 1024, buf, key_bytes, &yk_hmac_sha1); if (rc) { memcpy(cfg->ykcore_config.key, buf, sizeof(cfg->ykcore_config.key)); if (key_bytes == 20) { memcpy(cfg->ykcore_config.uid, buf + sizeof(cfg->ykcore_config.key), 4); } } memset (buf, 0, sizeof(buf)); return rc; } return 0; }