fbectest.c (7527B)
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 #include "blapi.h" 6 #include "ec.h" 7 #include "ecl-curve.h" 8 #include "prprf.h" 9 #include "basicutil.h" 10 #include "secder.h" 11 #include "secitem.h" 12 #include "nspr.h" 13 #include <stdio.h> 14 15 typedef struct { 16 ECCurveName curve; 17 int iterations; 18 char *privhex; 19 char *our_pubhex; 20 char *their_pubhex; 21 char *common_key; 22 char *name; 23 } ECDH_KAT; 24 25 typedef struct { 26 ECCurveName curve; 27 char *point; 28 char *name; 29 } ECDH_BAD; 30 31 #include "testvecs.h" 32 33 void 34 printBuf(const SECItem *item) 35 { 36 int i; 37 if (!item || !item->len) { 38 printf("(null)\n"); 39 return; 40 } 41 42 for (i = 0; i < item->len; i++) { 43 printf("%02x", item->data[i]); 44 } 45 printf("\n"); 46 } 47 48 /* Initialise test with basic curve populate with only the necessary things */ 49 SECStatus 50 init_params(ECParams *ecParams, ECCurveName curve, PLArenaPool **arena) 51 { 52 if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve)) { 53 return SECFailure; 54 } 55 *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 56 if (!*arena) { 57 return SECFailure; 58 } 59 ecParams->name = curve; 60 ecParams->type = ec_params_named; 61 ecParams->curveOID.data = NULL; 62 ecParams->curveOID.len = 0; 63 ecParams->curve.seed.data = NULL; 64 ecParams->curve.seed.len = 0; 65 ecParams->DEREncoding.data = NULL; 66 ecParams->DEREncoding.len = 0; 67 ecParams->arena = *arena; 68 ecParams->fieldID.size = ecCurve_map[curve]->size; 69 ecParams->fieldID.type = ec_field_plain; 70 ecParams->cofactor = ecCurve_map[curve]->cofactor; 71 72 return SECSuccess; 73 } 74 75 SECStatus 76 ectest_ecdh_kat(ECDH_KAT *kat) 77 { 78 ECCurveName curve = kat->curve; 79 ECParams ecParams = { 0 }; 80 ECPrivateKey *ecPriv = NULL; 81 SECItem theirKey = { siBuffer, NULL, 0 }; 82 SECStatus rv = SECFailure; 83 PLArenaPool *arena = NULL; 84 SECItem seed = { siBuffer, NULL, 0 }; 85 SECItem answer = { siBuffer, NULL, 0 }; 86 SECItem answer2 = { siBuffer, NULL, 0 }; 87 SECItem derived = { siBuffer, NULL, 0 }; 88 SECItem ecEncodedParams = { siBuffer, NULL, 0 }; 89 int i; 90 91 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 92 if (!arena) { 93 return SECFailure; 94 } 95 96 rv = SECU_ecName2params(curve, &ecEncodedParams); 97 if (rv != SECSuccess) { 98 goto cleanup; 99 } 100 EC_FillParams(arena, &ecEncodedParams, &ecParams); 101 102 if (kat->our_pubhex) { 103 SECU_HexString2SECItem(arena, &answer, kat->our_pubhex); 104 } 105 SECU_HexString2SECItem(arena, &seed, kat->privhex); 106 rv = EC_NewKeyFromSeed(&ecParams, &ecPriv, seed.data, seed.len); 107 if (rv != SECSuccess) { 108 rv = SECFailure; 109 goto cleanup; 110 } 111 if (kat->our_pubhex) { 112 if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) { 113 rv = SECFailure; 114 goto cleanup; 115 } 116 } 117 118 SECU_HexString2SECItem(arena, &theirKey, kat->their_pubhex); 119 SECU_HexString2SECItem(arena, &answer2, kat->common_key); 120 121 rv = EC_ValidatePublicKey(&ecParams, &theirKey); 122 if (rv != SECSuccess) { 123 printf("EC_ValidatePublicKey failed\n"); 124 goto cleanup; 125 } 126 127 for (i = 0; i < kat->iterations; ++i) { 128 rv = ECDH_Derive(&theirKey, &ecParams, &ecPriv->privateValue, PR_TRUE, &derived); 129 if (rv != SECSuccess) { 130 rv = SECFailure; 131 goto cleanup; 132 } 133 rv = SECITEM_CopyItem(ecParams.arena, &theirKey, &ecPriv->privateValue); 134 if (rv != SECSuccess) { 135 goto cleanup; 136 } 137 rv = SECITEM_CopyItem(ecParams.arena, &ecPriv->privateValue, &derived); 138 if (rv != SECSuccess) { 139 goto cleanup; 140 } 141 SECITEM_FreeItem(&derived, PR_FALSE); 142 } 143 144 if (SECITEM_CompareItem(&answer2, &ecPriv->privateValue) != SECEqual) { 145 printf("expected: "); 146 printBuf(&answer2); 147 printf("derived: "); 148 printBuf(&ecPriv->privateValue); 149 rv = SECFailure; 150 goto cleanup; 151 } 152 153 cleanup: 154 SECITEM_FreeItem(&ecEncodedParams, PR_FALSE); 155 PORT_FreeArena(arena, PR_FALSE); 156 if (ecPriv) { 157 PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE); 158 } 159 if (derived.data) { 160 SECITEM_FreeItem(&derived, PR_FALSE); 161 } 162 return rv; 163 } 164 165 SECStatus 166 ectest_validate_point(ECDH_BAD *bad) 167 { 168 ECParams ecParams = { 0 }; 169 SECItem point = { siBuffer, NULL, 0 }; 170 SECStatus rv = SECFailure; 171 PLArenaPool *arena = NULL; 172 173 rv = init_params(&ecParams, bad->curve, &arena); 174 if (rv != SECSuccess) { 175 return rv; 176 } 177 178 SECU_HexString2SECItem(arena, &point, bad->point); 179 rv = EC_ValidatePublicKey(&ecParams, &point); 180 181 PORT_FreeArena(arena, PR_FALSE); 182 return rv; 183 } 184 185 void 186 printUsage(char *prog) 187 { 188 printf("Usage: %s [-fp] [-nd]\n" 189 "\t-n: NIST curves\n" 190 "\t-d: non-NIST curves\n" 191 "You have to specify at at least one of n or d.\n" 192 "By default no tests are executed.\n", 193 prog); 194 } 195 196 /* Performs tests of elliptic curve cryptography over prime fields If 197 * tests fail, then it prints an error message, aborts, and returns an 198 * error code. Otherwise, returns 0. */ 199 int 200 main(int argv, char **argc) 201 { 202 SECStatus rv = SECSuccess; 203 int numkats = 0; 204 int i = 0; 205 int nist = 0; 206 int nonnist = 0; 207 208 for (i = 1; i < argv; i++) { 209 if (PL_strcasecmp(argc[i], "-n") == 0) { 210 nist = 1; 211 } else if (PL_strcasecmp(argc[i], "-d") == 0) { 212 nonnist = 1; 213 } else { 214 printUsage(argc[0]); 215 return 1; 216 } 217 } 218 if (!nist && !nonnist) { 219 printUsage(argc[0]); 220 return 1; 221 } 222 223 rv = SECOID_Init(); 224 if (rv != SECSuccess) { 225 SECU_PrintError("Error:", "SECOID_Init"); 226 goto cleanup; 227 } 228 229 /* Test P256, P384, P521 */ 230 if (nist) { 231 while (ecdh_testvecs[numkats].curve != ECCurve_pastLastCurve) { 232 numkats++; 233 } 234 printf("1..%d\n", numkats); 235 for (i = 0; ecdh_testvecs[i].curve != ECCurve_pastLastCurve; i++) { 236 if (ectest_ecdh_kat(&ecdh_testvecs[i]) != SECSuccess) { 237 printf("not okay %d - %s\n", i + 1, ecdh_testvecs[i].name); 238 rv = SECFailure; 239 } else { 240 printf("okay %d - %s\n", i + 1, ecdh_testvecs[i].name); 241 } 242 } 243 } 244 245 /* Test KAT for non-NIST curves */ 246 if (nonnist) { 247 for (i = 0; nonnist_testvecs[i].curve != ECCurve_pastLastCurve; i++) { 248 if (ectest_ecdh_kat(&nonnist_testvecs[i]) != SECSuccess) { 249 printf("not okay %d - %s\n", i + 1, nonnist_testvecs[i].name); 250 rv = SECFailure; 251 } else { 252 printf("okay %d - %s\n", i + 1, nonnist_testvecs[i].name); 253 } 254 } 255 for (i = 0; nonnist_testvecs_bad_values[i].curve != ECCurve_pastLastCurve; i++) { 256 if (ectest_validate_point(&nonnist_testvecs_bad_values[i]) == SECSuccess) { 257 printf("not okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name); 258 rv = SECFailure; 259 } else { 260 printf("okay %d - %s\n", i + 1, nonnist_testvecs_bad_values[i].name); 261 } 262 } 263 } 264 265 cleanup: 266 rv |= SECOID_Shutdown(); 267 268 if (rv != SECSuccess) { 269 printf("Error: exiting with error value\n"); 270 } 271 return rv; 272 }