1/* 2 * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. 4 * 5 * Licensed under the OpenSSL license (the "License"). You may not use 6 * this file except in compliance with the License. You can obtain a copy 7 * in the file LICENSE in the source distribution or at 8 * https://www.openssl.org/source/license.html 9 */ 10 11#include <openssl/ecdh.h> 12 13#include <string.h> 14 15#include <openssl/ec.h> 16#include <openssl/ec_key.h> 17#include <openssl/err.h> 18#include <openssl/mem.h> 19 20#include "../../internal.h" 21#include "../ec/internal.h" 22#include "../service_indicator/internal.h" 23 24 25int ECDH_compute_key_fips(uint8_t *out, size_t out_len, const EC_POINT *pub_key, 26 const EC_KEY *priv_key) { 27 boringssl_ensure_ecc_self_test(); 28 29 if (priv_key->priv_key == NULL) { 30 OPENSSL_PUT_ERROR(ECDH, ECDH_R_NO_PRIVATE_VALUE); 31 return 0; 32 } 33 const EC_SCALAR *const priv = &priv_key->priv_key->scalar; 34 const EC_GROUP *const group = EC_KEY_get0_group(priv_key); 35 if (EC_GROUP_cmp(group, pub_key->group, NULL) != 0) { 36 OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 37 return 0; 38 } 39 40 EC_JACOBIAN shared_point; 41 uint8_t buf[EC_MAX_BYTES]; 42 size_t buflen; 43 if (!ec_point_mul_scalar(group, &shared_point, &pub_key->raw, priv) || 44 !ec_get_x_coordinate_as_bytes(group, buf, &buflen, sizeof(buf), 45 &shared_point)) { 46 OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE); 47 return 0; 48 } 49 50 FIPS_service_indicator_lock_state(); 51 SHA256_CTX ctx; 52 SHA512_CTX ctx_512; 53 switch (out_len) { 54 case SHA224_DIGEST_LENGTH: 55 BCM_sha224_init(&ctx); 56 BCM_sha224_update(&ctx, buf, buflen); 57 BCM_sha224_final(out, &ctx); 58 break; 59 case SHA256_DIGEST_LENGTH: 60 BCM_sha256_init(&ctx); 61 BCM_sha256_update(&ctx, buf, buflen); 62 BCM_sha256_final(out, &ctx); 63 break; 64 case SHA384_DIGEST_LENGTH: 65 BCM_sha384_init(&ctx_512); 66 BCM_sha384_update(&ctx_512, buf, buflen); 67 BCM_sha384_final(out, &ctx_512); 68 break; 69 case SHA512_DIGEST_LENGTH: 70 BCM_sha512_init(&ctx_512); 71 BCM_sha512_update(&ctx_512, buf, buflen); 72 BCM_sha512_final(out, &ctx_512); 73 break; 74 default: 75 OPENSSL_PUT_ERROR(ECDH, ECDH_R_UNKNOWN_DIGEST_LENGTH); 76 FIPS_service_indicator_unlock_state(); 77 return 0; 78 } 79 FIPS_service_indicator_unlock_state(); 80 81 ECDH_verify_service_indicator(priv_key); 82 return 1; 83} 84