int init_crypto(crypto_ctx_t *cctx, uchar_t *pwd, int pwd_len, int crypto_alg, uchar_t *salt, int saltlen, uint64_t nonce, int enc_dec) { if (crypto_alg == CRYPTO_ALG_AES) { aes_ctx_t *actx = malloc(sizeof (aes_ctx_t)); if (enc_dec) { /* * Encryption init. */ cctx->salt = malloc(32); salt = cctx->salt; cctx->saltlen = 32; if (RAND_status() != 1 || RAND_bytes(salt, 32) != 1) { if (geturandom_bytes(salt) != 0) { uchar_t sb[64]; int b; struct timespec tp; b = 0; /* No good random pool is populated/available. What to do ? */ if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) { time((time_t *)&sb[b]); b += 8; } else { uint64_t v; v = tp.tv_sec * 1000UL + tp.tv_nsec; *((uint64_t *)&sb[b]) = v; b += 8; } *((uint32_t *)&sb[b]) = rand(); b += 4; *((uint32_t *)&sb[b]) = getpid(); b += 4; compute_checksum(&sb[b], CKSUM_SHA256, sb, b); b = 8 + 4; *((uint32_t *)&sb[b]) = rand(); compute_checksum(salt, CKSUM_SHA256, &sb[b], 32 + 4); } } /* * Zero nonce (arg #6) since it will be generated. */ if (aes_init(actx, salt, 32, pwd, pwd_len, 0, enc_dec) != 0) { fprintf(stderr, "Failed to initialize AES context\n"); return (-1); } } else { /* * Decryption init. * Pass given nonce and salt. */ if (saltlen > MAX_SALTLEN) { fprintf(stderr, "Salt too long. Max allowed length is %d\n", MAX_SALTLEN); return (-1); } cctx->salt = malloc(saltlen); memcpy(cctx->salt, salt, saltlen); if (aes_init(actx, cctx->salt, saltlen, pwd, pwd_len, nonce, enc_dec) != 0) { fprintf(stderr, "Failed to initialize AES context\n"); return (-1); } } cctx->crypto_ctx = actx; cctx->crypto_alg = crypto_alg; cctx->enc_dec = enc_dec; } else { fprintf(stderr, "Unrecognized algorithm code: %d\n", crypto_alg); return (-1); } return (0); }
int salsa20_init(salsa20_ctx_t *ctx, uchar_t *salt, int saltlen, uchar_t *pwd, int pwd_len, uchar_t *nonce, int enc) { struct timespec tp; uint64_t tv; uchar_t num[25]; uchar_t IV[32]; uchar_t *key = ctx->pkey; #ifndef _USE_PBK int logN; uint32_t r, p; uint64_t N; if (XSALSA20_CRYPTO_NONCEBYTES % 8) { log_msg(LOG_ERR, 0, "XSALSA20_CRYPTO_NONCEBYTES is not a multiple of 8!\n"); return (-1); } pickparams(&logN, &r, &p); N = (uint64_t)(1) << logN; if (crypto_scrypt(pwd, pwd_len, salt, saltlen, N, r, p, key, ctx->keylen)) { log_msg(LOG_ERR, 0, "Scrypt failed\n"); return (-1); } #else rv = PKCS5_PBKDF2_HMAC(pwd, pwd_len, salt, saltlen, PBE_ROUNDS, EVP_sha256(), ctx->keylen, key); if (rv != ctx->keylen) { log_msg(LOG_ERR, 0, "Key size is %d bytes - should be %d bits\n", i, ctx->keylen); return (-1); } #endif /* * Copy the key. XSalsa20 core cipher always uses a 256-bit key. If we are using a * 128-bit key then the key value is repeated twice to form a 256-bit value. * This approach is based on the Salsa20 code submitted to eSTREAM. See the function * ECRYPT_keysetup() in the Salsa20 submission: * http://www.ecrypt.eu.org/stream/svn/viewcvs.cgi/ecrypt/trunk/submissions/salsa20/full/ref/salsa20.c?rev=161&view=auto * * The input values corresponding to a 256-bit key contain repeated values if key * length is 128-bit. */ memcpy(ctx->key, key, ctx->keylen); if (ctx->keylen < XSALSA20_CRYPTO_KEYBYTES) { uchar_t *k; k = ctx->key + ctx->keylen; memcpy(k, key, XSALSA20_CRYPTO_KEYBYTES - ctx->keylen); } if (enc) { int i; uint64_t *n, *n1; // Derive 192-bit nonce if (RAND_status() != 1 || RAND_bytes(IV, XSALSA20_CRYPTO_NONCEBYTES) != 1) { if (geturandom_bytes(IV, XSALSA20_CRYPTO_NONCEBYTES) != 0) { if (clock_gettime(CLOCK_MONOTONIC, &tp) == -1) { time((time_t *)&tv); } else { tv = tp.tv_sec * 1000UL + tp.tv_nsec; } sprintf((char *)num, "%" PRIu64, tv); PKCS5_PBKDF2_HMAC((const char *)num, strlen((char *)num), salt, saltlen, PBE_ROUNDS, EVP_sha256(), 32, IV); } } n = (uint64_t *)IV; n1 = (uint64_t *)(ctx->nonce); for (i = 0; i < XSALSA20_CRYPTO_NONCEBYTES/8; i++) { *n1 = LE64(*n); n++; n1++; } // Nullify stack components memset(num, 0, 25); memset(IV, 0, 32); memset(&tp, 0, sizeof (tp)); tv = 0; } else { memcpy(ctx->nonce, nonce, XSALSA20_CRYPTO_NONCEBYTES); memset(nonce, 0, XSALSA20_CRYPTO_NONCEBYTES); } return (0); }