1279265Sdelphij/* crypto/constant_time_test.c */ 2296465Sdelphij/*- 3279265Sdelphij * Utilities for constant-time cryptography. 4279265Sdelphij * 5279265Sdelphij * Author: Emilia Kasper (emilia@openssl.org) 6279265Sdelphij * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley 7279265Sdelphij * (Google). 8279265Sdelphij * ==================================================================== 9279265Sdelphij * Copyright (c) 2014 The OpenSSL Project. All rights reserved. 10279265Sdelphij * 11279265Sdelphij * Redistribution and use in source and binary forms, with or without 12279265Sdelphij * modification, are permitted provided that the following conditions 13279265Sdelphij * are met: 14279265Sdelphij * 1. Redistributions of source code must retain the copyright 15279265Sdelphij * notice, this list of conditions and the following disclaimer. 16279265Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 17279265Sdelphij * notice, this list of conditions and the following disclaimer in the 18279265Sdelphij * documentation and/or other materials provided with the distribution. 19279265Sdelphij * 3. All advertising materials mentioning features or use of this software 20279265Sdelphij * must display the following acknowledgement: 21279265Sdelphij * "This product includes cryptographic software written by 22279265Sdelphij * Eric Young (eay@cryptsoft.com)" 23279265Sdelphij * The word 'cryptographic' can be left out if the rouines from the library 24279265Sdelphij * being used are not cryptographic related :-). 25279265Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from 26279265Sdelphij * the apps directory (application code) you must include an acknowledgement: 27279265Sdelphij * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 28279265Sdelphij * 29279265Sdelphij * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 30279265Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31279265Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32279265Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 33279265Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34279265Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35279265Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36279265Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37279265Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38279265Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39279265Sdelphij * SUCH DAMAGE. 40279265Sdelphij * 41279265Sdelphij * The licence and distribution terms for any publically available version or 42279265Sdelphij * derivative of this code cannot be changed. i.e. this code cannot simply be 43279265Sdelphij * copied and put under another distribution licence 44279265Sdelphij * [including the GNU Public Licence.] 45279265Sdelphij */ 46279265Sdelphij 47279265Sdelphij#include "../crypto/constant_time_locl.h" 48279265Sdelphij 49279265Sdelphij#include <limits.h> 50279265Sdelphij#include <stdio.h> 51279265Sdelphij#include <stdlib.h> 52279265Sdelphij 53279265Sdelphijstatic const unsigned int CONSTTIME_TRUE = (unsigned)(~0); 54279265Sdelphijstatic const unsigned int CONSTTIME_FALSE = 0; 55279265Sdelphijstatic const unsigned char CONSTTIME_TRUE_8 = 0xff; 56279265Sdelphijstatic const unsigned char CONSTTIME_FALSE_8 = 0; 57279265Sdelphij 58296465Sdelphijstatic int test_binary_op(unsigned int (*op) (unsigned int a, unsigned int b), 59296465Sdelphij const char *op_name, unsigned int a, unsigned int b, 60296465Sdelphij int is_true) 61296465Sdelphij{ 62296465Sdelphij unsigned c = op(a, b); 63296465Sdelphij if (is_true && c != CONSTTIME_TRUE) { 64296465Sdelphij fprintf(stderr, "Test failed for %s(%du, %du): expected %du " 65296465Sdelphij "(TRUE), got %du\n", op_name, a, b, CONSTTIME_TRUE, c); 66296465Sdelphij return 1; 67296465Sdelphij } else if (!is_true && c != CONSTTIME_FALSE) { 68296465Sdelphij fprintf(stderr, "Test failed for %s(%du, %du): expected %du " 69296465Sdelphij "(FALSE), got %du\n", op_name, a, b, CONSTTIME_FALSE, c); 70296465Sdelphij return 1; 71296465Sdelphij } 72296465Sdelphij return 0; 73296465Sdelphij} 74279265Sdelphij 75296465Sdelphijstatic int test_binary_op_8(unsigned 76296465Sdelphij char (*op) (unsigned int a, unsigned int b), 77296465Sdelphij const char *op_name, unsigned int a, 78296465Sdelphij unsigned int b, int is_true) 79296465Sdelphij{ 80296465Sdelphij unsigned char c = op(a, b); 81296465Sdelphij if (is_true && c != CONSTTIME_TRUE_8) { 82296465Sdelphij fprintf(stderr, "Test failed for %s(%du, %du): expected %u " 83296465Sdelphij "(TRUE), got %u\n", op_name, a, b, CONSTTIME_TRUE_8, c); 84296465Sdelphij return 1; 85296465Sdelphij } else if (!is_true && c != CONSTTIME_FALSE_8) { 86296465Sdelphij fprintf(stderr, "Test failed for %s(%du, %du): expected %u " 87296465Sdelphij "(FALSE), got %u\n", op_name, a, b, CONSTTIME_FALSE_8, c); 88296465Sdelphij return 1; 89296465Sdelphij } 90296465Sdelphij return 0; 91296465Sdelphij} 92279265Sdelphij 93279265Sdelphijstatic int test_is_zero(unsigned int a) 94296465Sdelphij{ 95296465Sdelphij unsigned int c = constant_time_is_zero(a); 96296465Sdelphij if (a == 0 && c != CONSTTIME_TRUE) { 97296465Sdelphij fprintf(stderr, "Test failed for constant_time_is_zero(%du): " 98296465Sdelphij "expected %du (TRUE), got %du\n", a, CONSTTIME_TRUE, c); 99296465Sdelphij return 1; 100296465Sdelphij } else if (a != 0 && c != CONSTTIME_FALSE) { 101296465Sdelphij fprintf(stderr, "Test failed for constant_time_is_zero(%du): " 102296465Sdelphij "expected %du (FALSE), got %du\n", a, CONSTTIME_FALSE, c); 103296465Sdelphij return 1; 104296465Sdelphij } 105296465Sdelphij return 0; 106296465Sdelphij} 107279265Sdelphij 108279265Sdelphijstatic int test_is_zero_8(unsigned int a) 109296465Sdelphij{ 110296465Sdelphij unsigned char c = constant_time_is_zero_8(a); 111296465Sdelphij if (a == 0 && c != CONSTTIME_TRUE_8) { 112296465Sdelphij fprintf(stderr, "Test failed for constant_time_is_zero(%du): " 113296465Sdelphij "expected %u (TRUE), got %u\n", a, CONSTTIME_TRUE_8, c); 114296465Sdelphij return 1; 115296465Sdelphij } else if (a != 0 && c != CONSTTIME_FALSE) { 116296465Sdelphij fprintf(stderr, "Test failed for constant_time_is_zero(%du): " 117296465Sdelphij "expected %u (FALSE), got %u\n", a, CONSTTIME_FALSE_8, c); 118296465Sdelphij return 1; 119296465Sdelphij } 120296465Sdelphij return 0; 121296465Sdelphij} 122279265Sdelphij 123279265Sdelphijstatic int test_select(unsigned int a, unsigned int b) 124296465Sdelphij{ 125296465Sdelphij unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b); 126296465Sdelphij if (selected != a) { 127296465Sdelphij fprintf(stderr, "Test failed for constant_time_select(%du, %du," 128296465Sdelphij "%du): expected %du(first value), got %du\n", 129296465Sdelphij CONSTTIME_TRUE, a, b, a, selected); 130296465Sdelphij return 1; 131296465Sdelphij } 132296465Sdelphij selected = constant_time_select(CONSTTIME_FALSE, a, b); 133296465Sdelphij if (selected != b) { 134296465Sdelphij fprintf(stderr, "Test failed for constant_time_select(%du, %du," 135296465Sdelphij "%du): expected %du(second value), got %du\n", 136296465Sdelphij CONSTTIME_FALSE, a, b, b, selected); 137296465Sdelphij return 1; 138296465Sdelphij } 139296465Sdelphij return 0; 140296465Sdelphij} 141279265Sdelphij 142279265Sdelphijstatic int test_select_8(unsigned char a, unsigned char b) 143296465Sdelphij{ 144296465Sdelphij unsigned char selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b); 145296465Sdelphij if (selected != a) { 146296465Sdelphij fprintf(stderr, "Test failed for constant_time_select(%u, %u," 147296465Sdelphij "%u): expected %u(first value), got %u\n", 148296465Sdelphij CONSTTIME_TRUE, a, b, a, selected); 149296465Sdelphij return 1; 150296465Sdelphij } 151296465Sdelphij selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b); 152296465Sdelphij if (selected != b) { 153296465Sdelphij fprintf(stderr, "Test failed for constant_time_select(%u, %u," 154296465Sdelphij "%u): expected %u(second value), got %u\n", 155296465Sdelphij CONSTTIME_FALSE, a, b, b, selected); 156296465Sdelphij return 1; 157296465Sdelphij } 158296465Sdelphij return 0; 159296465Sdelphij} 160279265Sdelphij 161279265Sdelphijstatic int test_select_int(int a, int b) 162296465Sdelphij{ 163296465Sdelphij int selected = constant_time_select_int(CONSTTIME_TRUE, a, b); 164296465Sdelphij if (selected != a) { 165296465Sdelphij fprintf(stderr, "Test failed for constant_time_select(%du, %d," 166296465Sdelphij "%d): expected %d(first value), got %d\n", 167296465Sdelphij CONSTTIME_TRUE, a, b, a, selected); 168296465Sdelphij return 1; 169296465Sdelphij } 170296465Sdelphij selected = constant_time_select_int(CONSTTIME_FALSE, a, b); 171296465Sdelphij if (selected != b) { 172296465Sdelphij fprintf(stderr, "Test failed for constant_time_select(%du, %d," 173296465Sdelphij "%d): expected %d(second value), got %d\n", 174296465Sdelphij CONSTTIME_FALSE, a, b, b, selected); 175296465Sdelphij return 1; 176296465Sdelphij } 177296465Sdelphij return 0; 178296465Sdelphij} 179279265Sdelphij 180279265Sdelphijstatic int test_eq_int(int a, int b) 181296465Sdelphij{ 182296465Sdelphij unsigned int equal = constant_time_eq_int(a, b); 183296465Sdelphij if (a == b && equal != CONSTTIME_TRUE) { 184296465Sdelphij fprintf(stderr, "Test failed for constant_time_eq_int(%d, %d): " 185296465Sdelphij "expected %du(TRUE), got %du\n", a, b, CONSTTIME_TRUE, equal); 186296465Sdelphij return 1; 187296465Sdelphij } else if (a != b && equal != CONSTTIME_FALSE) { 188296465Sdelphij fprintf(stderr, "Test failed for constant_time_eq_int(%d, %d): " 189296465Sdelphij "expected %du(FALSE), got %du\n", 190296465Sdelphij a, b, CONSTTIME_FALSE, equal); 191296465Sdelphij return 1; 192296465Sdelphij } 193296465Sdelphij return 0; 194296465Sdelphij} 195279265Sdelphij 196279265Sdelphijstatic int test_eq_int_8(int a, int b) 197296465Sdelphij{ 198296465Sdelphij unsigned char equal = constant_time_eq_int_8(a, b); 199296465Sdelphij if (a == b && equal != CONSTTIME_TRUE_8) { 200296465Sdelphij fprintf(stderr, "Test failed for constant_time_eq_int_8(%d, %d): " 201296465Sdelphij "expected %u(TRUE), got %u\n", a, b, CONSTTIME_TRUE_8, equal); 202296465Sdelphij return 1; 203296465Sdelphij } else if (a != b && equal != CONSTTIME_FALSE_8) { 204296465Sdelphij fprintf(stderr, "Test failed for constant_time_eq_int_8(%d, %d): " 205296465Sdelphij "expected %u(FALSE), got %u\n", 206296465Sdelphij a, b, CONSTTIME_FALSE_8, equal); 207296465Sdelphij return 1; 208296465Sdelphij } 209296465Sdelphij return 0; 210296465Sdelphij} 211279265Sdelphij 212296465Sdelphijstatic unsigned int test_values[] = 213296465Sdelphij { 0, 1, 1024, 12345, 32000, UINT_MAX / 2 - 1, 214296465Sdelphij UINT_MAX / 2, UINT_MAX / 2 + 1, UINT_MAX - 1, 215296465Sdelphij UINT_MAX 216296465Sdelphij}; 217279265Sdelphij 218296465Sdelphijstatic unsigned char test_values_8[] = 219296465Sdelphij { 0, 1, 2, 20, 32, 127, 128, 129, 255 }; 220279265Sdelphij 221296465Sdelphijstatic int signed_test_values[] = { 0, 1, -1, 1024, -1024, 12345, -12345, 222296465Sdelphij 32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, 223296465Sdelphij INT_MIN + 1 224296465Sdelphij}; 225279265Sdelphij 226279265Sdelphijint main(int argc, char *argv[]) 227296465Sdelphij{ 228296465Sdelphij unsigned int a, b, i, j; 229296465Sdelphij int c, d; 230296465Sdelphij unsigned char e, f; 231296465Sdelphij int num_failed = 0, num_all = 0; 232296465Sdelphij fprintf(stdout, "Testing constant time operations...\n"); 233279265Sdelphij 234296465Sdelphij for (i = 0; i < sizeof(test_values) / sizeof(int); ++i) { 235296465Sdelphij a = test_values[i]; 236296465Sdelphij num_failed += test_is_zero(a); 237296465Sdelphij num_failed += test_is_zero_8(a); 238296465Sdelphij num_all += 2; 239296465Sdelphij for (j = 0; j < sizeof(test_values) / sizeof(int); ++j) { 240296465Sdelphij b = test_values[j]; 241296465Sdelphij num_failed += test_binary_op(&constant_time_lt, 242296465Sdelphij "constant_time_lt", a, b, a < b); 243296465Sdelphij num_failed += test_binary_op_8(&constant_time_lt_8, 244296465Sdelphij "constant_time_lt_8", a, b, a < b); 245296465Sdelphij num_failed += test_binary_op(&constant_time_lt, 246296465Sdelphij "constant_time_lt_8", b, a, b < a); 247296465Sdelphij num_failed += test_binary_op_8(&constant_time_lt_8, 248296465Sdelphij "constant_time_lt_8", b, a, b < a); 249296465Sdelphij num_failed += test_binary_op(&constant_time_ge, 250296465Sdelphij "constant_time_ge", a, b, a >= b); 251296465Sdelphij num_failed += test_binary_op_8(&constant_time_ge_8, 252296465Sdelphij "constant_time_ge_8", a, b, 253296465Sdelphij a >= b); 254296465Sdelphij num_failed += 255296465Sdelphij test_binary_op(&constant_time_ge, "constant_time_ge", b, a, 256296465Sdelphij b >= a); 257296465Sdelphij num_failed += 258296465Sdelphij test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8", b, 259296465Sdelphij a, b >= a); 260296465Sdelphij num_failed += 261296465Sdelphij test_binary_op(&constant_time_eq, "constant_time_eq", a, b, 262296465Sdelphij a == b); 263296465Sdelphij num_failed += 264296465Sdelphij test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8", a, 265296465Sdelphij b, a == b); 266296465Sdelphij num_failed += 267296465Sdelphij test_binary_op(&constant_time_eq, "constant_time_eq", b, a, 268296465Sdelphij b == a); 269296465Sdelphij num_failed += 270296465Sdelphij test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8", b, 271296465Sdelphij a, b == a); 272296465Sdelphij num_failed += test_select(a, b); 273296465Sdelphij num_all += 13; 274296465Sdelphij } 275296465Sdelphij } 276279265Sdelphij 277296465Sdelphij for (i = 0; i < sizeof(signed_test_values) / sizeof(int); ++i) { 278296465Sdelphij c = signed_test_values[i]; 279296465Sdelphij for (j = 0; j < sizeof(signed_test_values) / sizeof(int); ++j) { 280296465Sdelphij d = signed_test_values[j]; 281296465Sdelphij num_failed += test_select_int(c, d); 282296465Sdelphij num_failed += test_eq_int(c, d); 283296465Sdelphij num_failed += test_eq_int_8(c, d); 284296465Sdelphij num_all += 3; 285296465Sdelphij } 286296465Sdelphij } 287279265Sdelphij 288296465Sdelphij for (i = 0; i < sizeof(test_values_8); ++i) { 289296465Sdelphij e = test_values_8[i]; 290296465Sdelphij for (j = 0; j < sizeof(test_values_8); ++j) { 291296465Sdelphij f = test_values_8[j]; 292296465Sdelphij num_failed += test_select_8(e, f); 293296465Sdelphij num_all += 1; 294296465Sdelphij } 295296465Sdelphij } 296279265Sdelphij 297296465Sdelphij if (!num_failed) { 298296465Sdelphij fprintf(stdout, "ok (ran %d tests)\n", num_all); 299296465Sdelphij return EXIT_SUCCESS; 300296465Sdelphij } else { 301296465Sdelphij fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all); 302296465Sdelphij return EXIT_FAILURE; 303296465Sdelphij } 304296465Sdelphij} 305