ecp_25519.c (4861B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 /* curve 25519 https://www.rfc-editor.org/rfc/rfc7748.txt */ 6 7 #ifdef FREEBL_NO_DEPEND 8 #include "../stubs.h" 9 #endif 10 11 #include "ecl-priv.h" 12 #include "secitem.h" 13 #include "secerr.h" 14 #include "secport.h" 15 #include <stdlib.h> 16 #include <stdio.h> 17 18 /* 19 * point validation is not necessary in general. But this checks a point (px) 20 * against some known bad values. 21 */ 22 SECStatus 23 ec_Curve25519_pt_validate(const SECItem *px) 24 { 25 PRUint8 *p; 26 PRUint64 i; 27 PRUint8 forbiddenValues[12][32] = { 28 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 30 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 32 { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 36 { 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 37 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 38 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 39 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 }, 40 { 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 41 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 42 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 43 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 }, 44 { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 45 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 46 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 47 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, 48 { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 49 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 50 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 51 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, 52 { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 53 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 54 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 55 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, 56 { 0xcd, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 57 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 58 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, 59 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x80 }, 60 { 0x4c, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, 61 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, 62 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, 63 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0xd7 }, 64 { 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 65 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 67 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 68 { 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 69 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 70 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 71 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 72 { 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 73 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 74 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 75 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, 76 }; 77 78 if (px->len == 32) { 79 p = px->data; 80 } else { 81 return SECFailure; 82 } 83 84 for (i = 0; i < PR_ARRAY_SIZE(forbiddenValues); ++i) { 85 if (NSS_SecureMemcmp(p, forbiddenValues[i], px->len) == 0) { 86 return SECFailure; 87 } 88 } 89 90 return SECSuccess; 91 } 92 93 /* 94 * scalar validation is not necessary. 95 */ 96 SECStatus 97 ec_Curve25519_scalar_validate(const SECItem *scalar) 98 { 99 if (!scalar || !scalar->data) { 100 PORT_SetError(SEC_ERROR_INVALID_ARGS); 101 return SECFailure; 102 } 103 104 if (scalar->len != 32) { 105 PORT_SetError(SEC_ERROR_BAD_KEY); 106 return SECFailure; 107 } 108 return SECSuccess; 109 } 110 111 /* 112 * Scalar multiplication for Curve25519. 113 * If P == NULL, the base point is used. 114 * Returns X = k*P 115 */ 116 SECStatus 117 ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P) 118 { 119 PRUint8 *px; 120 PRUint8 basePoint[32] = { 9 }; 121 122 if (!P) { 123 px = basePoint; 124 } else { 125 PORT_Assert(P->len == 32); 126 if (P->len != 32) { 127 return SECFailure; 128 } 129 px = P->data; 130 } 131 if (k->len != 32) { 132 return SECFailure; 133 } 134 #ifndef UNSAFE_FUZZER_MODE 135 SECStatus rv = ec_Curve25519_mul(X->data, k->data, px); 136 if (NSS_SecureMemcmpZero(X->data, X->len) == 0) { 137 return SECFailure; 138 } 139 return rv; 140 #else 141 return px != NULL; 142 #endif 143 }