1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"); 5e1051a39Sopenharmony_ci * you may not use this file except in compliance with the License. 6e1051a39Sopenharmony_ci * You may obtain a copy of the License at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci * or in the file LICENSE in the source distribution. 9e1051a39Sopenharmony_ci */ 10e1051a39Sopenharmony_ci 11e1051a39Sopenharmony_ci#include "internal/nelem.h" 12e1051a39Sopenharmony_ci#include "testutil.h" 13e1051a39Sopenharmony_ci 14e1051a39Sopenharmony_ci#include <stdio.h> 15e1051a39Sopenharmony_ci#include <stdlib.h> 16e1051a39Sopenharmony_ci#include <string.h> 17e1051a39Sopenharmony_ci#include <ctype.h> 18e1051a39Sopenharmony_ci 19e1051a39Sopenharmony_ci#define NUM_REPEATS "1000000" 20e1051a39Sopenharmony_ci 21e1051a39Sopenharmony_cistatic ossl_intmax_t num_repeats; 22e1051a39Sopenharmony_cistatic int print_mode = 0; 23e1051a39Sopenharmony_ci 24e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC 25e1051a39Sopenharmony_ci# include <openssl/ec.h> 26e1051a39Sopenharmony_ci# include <openssl/err.h> 27e1051a39Sopenharmony_ci# include <openssl/obj_mac.h> 28e1051a39Sopenharmony_ci# include <openssl/objects.h> 29e1051a39Sopenharmony_ci# include <openssl/rand.h> 30e1051a39Sopenharmony_ci# include <openssl/bn.h> 31e1051a39Sopenharmony_ci# include <openssl/opensslconf.h> 32e1051a39Sopenharmony_ci 33e1051a39Sopenharmony_cistatic const char *kP256DefaultResult = 34e1051a39Sopenharmony_ci "A1E24B223B8E81BC1FFF99BAFB909EDB895FACDE7D6DA5EF5E7B3255FB378E0F"; 35e1051a39Sopenharmony_ci 36e1051a39Sopenharmony_ci/* 37e1051a39Sopenharmony_ci * Perform a deterministic walk on the curve, by starting from |point| and 38e1051a39Sopenharmony_ci * using the X-coordinate of the previous point as the next scalar for 39e1051a39Sopenharmony_ci * point multiplication. 40e1051a39Sopenharmony_ci * Returns the X-coordinate of the end result or NULL on error. 41e1051a39Sopenharmony_ci */ 42e1051a39Sopenharmony_cistatic BIGNUM *walk_curve(const EC_GROUP *group, EC_POINT *point, 43e1051a39Sopenharmony_ci ossl_intmax_t num) 44e1051a39Sopenharmony_ci{ 45e1051a39Sopenharmony_ci BIGNUM *scalar = NULL; 46e1051a39Sopenharmony_ci ossl_intmax_t i; 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci if (!TEST_ptr(scalar = BN_new()) 49e1051a39Sopenharmony_ci || !TEST_true(EC_POINT_get_affine_coordinates(group, point, scalar, 50e1051a39Sopenharmony_ci NULL, NULL))) 51e1051a39Sopenharmony_ci goto err; 52e1051a39Sopenharmony_ci 53e1051a39Sopenharmony_ci for (i = 0; i < num; i++) { 54e1051a39Sopenharmony_ci if (!TEST_true(EC_POINT_mul(group, point, NULL, point, scalar, NULL)) 55e1051a39Sopenharmony_ci || !TEST_true(EC_POINT_get_affine_coordinates(group, point, 56e1051a39Sopenharmony_ci scalar, 57e1051a39Sopenharmony_ci NULL, NULL))) 58e1051a39Sopenharmony_ci goto err; 59e1051a39Sopenharmony_ci } 60e1051a39Sopenharmony_ci return scalar; 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_cierr: 63e1051a39Sopenharmony_ci BN_free(scalar); 64e1051a39Sopenharmony_ci return NULL; 65e1051a39Sopenharmony_ci} 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_cistatic int test_curve(void) 68e1051a39Sopenharmony_ci{ 69e1051a39Sopenharmony_ci EC_GROUP *group = NULL; 70e1051a39Sopenharmony_ci EC_POINT *point = NULL; 71e1051a39Sopenharmony_ci BIGNUM *result = NULL, *expected_result = NULL; 72e1051a39Sopenharmony_ci int ret = 0; 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_ci /* 75e1051a39Sopenharmony_ci * We currently hard-code P-256, though adaptation to other curves. 76e1051a39Sopenharmony_ci * would be straightforward. 77e1051a39Sopenharmony_ci */ 78e1051a39Sopenharmony_ci if (!TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) 79e1051a39Sopenharmony_ci || !TEST_ptr(point = EC_POINT_dup(EC_GROUP_get0_generator(group), 80e1051a39Sopenharmony_ci group)) 81e1051a39Sopenharmony_ci || !TEST_ptr(result = walk_curve(group, point, num_repeats))) 82e1051a39Sopenharmony_ci return 0; 83e1051a39Sopenharmony_ci 84e1051a39Sopenharmony_ci if (print_mode) { 85e1051a39Sopenharmony_ci BN_print(bio_out, result); 86e1051a39Sopenharmony_ci BIO_printf(bio_out, "\n"); 87e1051a39Sopenharmony_ci ret = 1; 88e1051a39Sopenharmony_ci } else { 89e1051a39Sopenharmony_ci if (!TEST_true(BN_hex2bn(&expected_result, kP256DefaultResult)) 90e1051a39Sopenharmony_ci || !TEST_ptr(expected_result) 91e1051a39Sopenharmony_ci || !TEST_BN_eq(result, expected_result)) 92e1051a39Sopenharmony_ci goto err; 93e1051a39Sopenharmony_ci ret = 1; 94e1051a39Sopenharmony_ci } 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_cierr: 97e1051a39Sopenharmony_ci EC_GROUP_free(group); 98e1051a39Sopenharmony_ci EC_POINT_free(point); 99e1051a39Sopenharmony_ci BN_free(result); 100e1051a39Sopenharmony_ci BN_free(expected_result); 101e1051a39Sopenharmony_ci return ret; 102e1051a39Sopenharmony_ci} 103e1051a39Sopenharmony_ci#endif 104e1051a39Sopenharmony_ci 105e1051a39Sopenharmony_citypedef enum OPTION_choice { 106e1051a39Sopenharmony_ci OPT_ERR = -1, 107e1051a39Sopenharmony_ci OPT_EOF = 0, 108e1051a39Sopenharmony_ci OPT_NUM_REPEATS, 109e1051a39Sopenharmony_ci OPT_TEST_ENUM 110e1051a39Sopenharmony_ci} OPTION_CHOICE; 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ciconst OPTIONS *test_get_options(void) 113e1051a39Sopenharmony_ci{ 114e1051a39Sopenharmony_ci static const OPTIONS test_options[] = { 115e1051a39Sopenharmony_ci OPT_TEST_OPTIONS_DEFAULT_USAGE, 116e1051a39Sopenharmony_ci { "num", OPT_NUM_REPEATS, 'M', "Number of repeats" }, 117e1051a39Sopenharmony_ci { NULL } 118e1051a39Sopenharmony_ci }; 119e1051a39Sopenharmony_ci return test_options; 120e1051a39Sopenharmony_ci} 121e1051a39Sopenharmony_ci 122e1051a39Sopenharmony_ci/* 123e1051a39Sopenharmony_ci * Stress test the curve. If the '-num' argument is given, runs the loop 124e1051a39Sopenharmony_ci * |num| times and prints the resulting X-coordinate. Otherwise runs the test 125e1051a39Sopenharmony_ci * the default number of times and compares against the expected result. 126e1051a39Sopenharmony_ci */ 127e1051a39Sopenharmony_ciint setup_tests(void) 128e1051a39Sopenharmony_ci{ 129e1051a39Sopenharmony_ci OPTION_CHOICE o; 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_ci if (!opt_intmax(NUM_REPEATS, &num_repeats)) { 132e1051a39Sopenharmony_ci TEST_error("Cannot parse " NUM_REPEATS); 133e1051a39Sopenharmony_ci return 0; 134e1051a39Sopenharmony_ci } 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_ci while ((o = opt_next()) != OPT_EOF) { 137e1051a39Sopenharmony_ci switch (o) { 138e1051a39Sopenharmony_ci case OPT_NUM_REPEATS: 139e1051a39Sopenharmony_ci if (!opt_intmax(opt_arg(), &num_repeats) 140e1051a39Sopenharmony_ci || num_repeats < 0) 141e1051a39Sopenharmony_ci return 0; 142e1051a39Sopenharmony_ci print_mode = 1; 143e1051a39Sopenharmony_ci break; 144e1051a39Sopenharmony_ci case OPT_TEST_CASES: 145e1051a39Sopenharmony_ci break; 146e1051a39Sopenharmony_ci default: 147e1051a39Sopenharmony_ci case OPT_ERR: 148e1051a39Sopenharmony_ci return 0; 149e1051a39Sopenharmony_ci } 150e1051a39Sopenharmony_ci } 151e1051a39Sopenharmony_ci 152e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC 153e1051a39Sopenharmony_ci ADD_TEST(test_curve); 154e1051a39Sopenharmony_ci#endif 155e1051a39Sopenharmony_ci return 1; 156e1051a39Sopenharmony_ci} 157