int ssh_kdf(struct ssh_crypto_struct *crypto, unsigned char *key, size_t key_len, int key_type, unsigned char *output, size_t requested_len) { EVP_KDF_CTX *ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF); int rc; if (ctx == NULL) { return -1; } rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, sshkdf_digest_to_md(crypto->digest_type)); if (rc != 1) { goto out; } rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, key, key_len); if (rc != 1) { goto out; } rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, crypto->secret_hash, crypto->digest_len); if (rc != 1) { goto out; } rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, key_type); if (rc != 1) { goto out; } rc = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID, crypto->session_id, crypto->digest_len); if (rc != 1) { goto out; } rc = EVP_KDF_derive(ctx, output, requested_len); if (rc != 1) { goto out; } out: EVP_KDF_CTX_free(ctx); if (rc < 0) { return rc; } return 0; }
int EVP_PBE_scrypt(const char *pass, size_t passlen, const unsigned char *salt, size_t saltlen, uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, unsigned char *key, size_t keylen) { const char *empty = ""; int rv = 1; EVP_KDF_CTX *kctx; if (r > UINT32_MAX || p > UINT32_MAX) { EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_PARAMETER_TOO_LARGE); return 0; } /* Maintain existing behaviour. */ if (pass == NULL) { pass = empty; passlen = 0; } if (salt == NULL) { salt = (const unsigned char *)empty; saltlen = 0; } if (maxmem == 0) maxmem = SCRYPT_MAX_MEM; kctx = EVP_KDF_CTX_new_id(EVP_KDF_SCRYPT); if (kctx == NULL) return 0; if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, pass, (size_t)passlen) != 1 || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, salt, (size_t)saltlen) != 1 || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_N, N) != 1 || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_R, (uint32_t)r) != 1 || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SCRYPT_P, (uint32_t)p) != 1 || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MAXMEM_BYTES, maxmem) != 1 || EVP_KDF_derive(kctx, key, keylen) != 1) rv = 0; EVP_KDF_CTX_free(kctx); return rv; }
int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, const unsigned char *salt, int saltlen, int iter, const EVP_MD *digest, int keylen, unsigned char *out) { const char *empty = ""; int rv = 1; EVP_KDF_CTX *kctx; /* Keep documented behaviour. */ if (pass == NULL) { pass = empty; passlen = 0; } else if (passlen == -1) { passlen = strlen(pass); } if (salt == NULL && saltlen == 0) salt = (unsigned char *)empty; kctx = EVP_KDF_CTX_new_id(EVP_KDF_PBKDF2); if (kctx == NULL) return 0; if (EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_PASS, pass, (size_t)passlen) != 1 || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_SALT, salt, (size_t)saltlen) != 1 || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_ITER, iter) != 1 || EVP_KDF_ctrl(kctx, EVP_KDF_CTRL_SET_MD, digest) != 1 || EVP_KDF_derive(kctx, out, keylen) != 1) rv = 0; EVP_KDF_CTX_free(kctx); # ifdef OPENSSL_DEBUG_PKCS5V2 fprintf(stderr, "Password:\n"); h__dump(pass, passlen); fprintf(stderr, "Salt:\n"); h__dump(salt, saltlen); fprintf(stderr, "Iteration count %d\n", iter); fprintf(stderr, "Key:\n"); h__dump(out, keylen); # endif return rv; }