/* * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ #include #include #include #include #include #include #include "../../internal.h" #include "../ec/internal.h" #include "../service_indicator/internal.h" int ECDH_compute_key_fips(uint8_t *out, size_t out_len, const EC_POINT *pub_key, const EC_KEY *priv_key) { boringssl_ensure_ecc_self_test(); if (priv_key->priv_key == NULL) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_NO_PRIVATE_VALUE); return 0; } const EC_SCALAR *const priv = &priv_key->priv_key->scalar; const EC_GROUP *const group = EC_KEY_get0_group(priv_key); if (EC_GROUP_cmp(group, pub_key->group, NULL) != 0) { OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); return 0; } EC_JACOBIAN shared_point; uint8_t buf[EC_MAX_BYTES]; size_t buflen; if (!ec_point_mul_scalar(group, &shared_point, &pub_key->raw, priv) || !ec_get_x_coordinate_as_bytes(group, buf, &buflen, sizeof(buf), &shared_point)) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE); return 0; } FIPS_service_indicator_lock_state(); SHA256_CTX ctx; SHA512_CTX ctx_512; switch (out_len) { case SHA224_DIGEST_LENGTH: BCM_sha224_init(&ctx); BCM_sha224_update(&ctx, buf, buflen); BCM_sha224_final(out, &ctx); break; case SHA256_DIGEST_LENGTH: BCM_sha256_init(&ctx); BCM_sha256_update(&ctx, buf, buflen); BCM_sha256_final(out, &ctx); break; case SHA384_DIGEST_LENGTH: BCM_sha384_init(&ctx_512); BCM_sha384_update(&ctx_512, buf, buflen); BCM_sha384_final(out, &ctx_512); break; case SHA512_DIGEST_LENGTH: BCM_sha512_init(&ctx_512); BCM_sha512_update(&ctx_512, buf, buflen); BCM_sha512_final(out, &ctx_512); break; default: OPENSSL_PUT_ERROR(ECDH, ECDH_R_UNKNOWN_DIGEST_LENGTH); FIPS_service_indicator_unlock_state(); return 0; } FIPS_service_indicator_unlock_state(); ECDH_verify_service_indicator(priv_key); return 1; }