security/nss/cmd/ecperf/ecperf.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/cmd/ecperf/ecperf.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,726 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "blapi.h"
     1.9 +#include "ec.h"
    1.10 +#include "ecl-curve.h"
    1.11 +#include "nss.h"
    1.12 +#include "secutil.h"
    1.13 +#include "pkcs11.h"
    1.14 +#include <nspr.h>
    1.15 +#include <stdio.h>
    1.16 +#include <strings.h>
    1.17 +#include <assert.h>
    1.18 +
    1.19 +#include <time.h>
    1.20 +#include <sys/time.h>
    1.21 +#include <sys/resource.h>
    1.22 +
    1.23 +#define __PASTE(x,y)    x##y
    1.24 +
    1.25 +/*
    1.26 + * Get the NSS specific PKCS #11 function names.
    1.27 + */
    1.28 +#undef CK_PKCS11_FUNCTION_INFO
    1.29 +#undef CK_NEED_ARG_LIST
    1.30 +
    1.31 +#define CK_EXTERN extern
    1.32 +#define CK_PKCS11_FUNCTION_INFO(func) \
    1.33 +		CK_RV __PASTE(NS,func)
    1.34 +#define CK_NEED_ARG_LIST	1
    1.35 +
    1.36 +#include "pkcs11f.h"
    1.37 +
    1.38 +
    1.39 +
    1.40 +/* mapping between ECCurveName enum and pointers to ECCurveParams */
    1.41 +static SECOidTag ecCurve_oid_map[] = {
    1.42 +    SEC_OID_UNKNOWN,	/* ECCurve_noName */
    1.43 +    SEC_OID_ANSIX962_EC_PRIME192V1,    /* ECCurve_NIST_P192 */
    1.44 +    SEC_OID_SECG_EC_SECP224R1,    /* ECCurve_NIST_P224 */
    1.45 +    SEC_OID_ANSIX962_EC_PRIME256V1,    /* ECCurve_NIST_P256 */
    1.46 +    SEC_OID_SECG_EC_SECP384R1,    /* ECCurve_NIST_P384 */
    1.47 +    SEC_OID_SECG_EC_SECP521R1,    /* ECCurve_NIST_P521 */
    1.48 +    SEC_OID_SECG_EC_SECT163K1,    /* ECCurve_NIST_K163 */
    1.49 +    SEC_OID_SECG_EC_SECT163R1,    /* ECCurve_NIST_B163 */
    1.50 +    SEC_OID_SECG_EC_SECT233K1,    /* ECCurve_NIST_K233 */
    1.51 +    SEC_OID_SECG_EC_SECT233R1,    /* ECCurve_NIST_B233 */
    1.52 +    SEC_OID_SECG_EC_SECT283K1,    /* ECCurve_NIST_K283 */
    1.53 +    SEC_OID_SECG_EC_SECT283R1,    /* ECCurve_NIST_B283 */
    1.54 +    SEC_OID_SECG_EC_SECT409K1,    /* ECCurve_NIST_K409 */
    1.55 +    SEC_OID_SECG_EC_SECT409R1,    /* ECCurve_NIST_B409 */
    1.56 +    SEC_OID_SECG_EC_SECT571K1,    /* ECCurve_NIST_K571 */
    1.57 +    SEC_OID_SECG_EC_SECT571R1,    /* ECCurve_NIST_B571 */
    1.58 +    SEC_OID_ANSIX962_EC_PRIME192V2,    
    1.59 +    SEC_OID_ANSIX962_EC_PRIME192V3,
    1.60 +    SEC_OID_ANSIX962_EC_PRIME239V1,
    1.61 +    SEC_OID_ANSIX962_EC_PRIME239V2,
    1.62 +    SEC_OID_ANSIX962_EC_PRIME239V3,
    1.63 +	SEC_OID_ANSIX962_EC_C2PNB163V1,
    1.64 +	SEC_OID_ANSIX962_EC_C2PNB163V2,
    1.65 +	SEC_OID_ANSIX962_EC_C2PNB163V3,
    1.66 +    SEC_OID_ANSIX962_EC_C2PNB176V1,
    1.67 +    SEC_OID_ANSIX962_EC_C2TNB191V1,
    1.68 +    SEC_OID_ANSIX962_EC_C2TNB191V2,
    1.69 +    SEC_OID_ANSIX962_EC_C2TNB191V3,
    1.70 +    SEC_OID_ANSIX962_EC_C2PNB208W1,
    1.71 +    SEC_OID_ANSIX962_EC_C2TNB239V1,
    1.72 +    SEC_OID_ANSIX962_EC_C2TNB239V2,
    1.73 +    SEC_OID_ANSIX962_EC_C2TNB239V3,
    1.74 +    SEC_OID_ANSIX962_EC_C2PNB272W1,
    1.75 +    SEC_OID_ANSIX962_EC_C2PNB304W1,
    1.76 +    SEC_OID_ANSIX962_EC_C2TNB359V1,
    1.77 +    SEC_OID_ANSIX962_EC_C2PNB368W1,
    1.78 +    SEC_OID_ANSIX962_EC_C2TNB431R1,
    1.79 +    SEC_OID_SECG_EC_SECP112R1,
    1.80 +    SEC_OID_SECG_EC_SECP112R2,
    1.81 +    SEC_OID_SECG_EC_SECP128R1,
    1.82 +    SEC_OID_SECG_EC_SECP128R2,
    1.83 +    SEC_OID_SECG_EC_SECP160K1,
    1.84 +    SEC_OID_SECG_EC_SECP160R1,
    1.85 +    SEC_OID_SECG_EC_SECP160R2,
    1.86 +    SEC_OID_SECG_EC_SECP192K1,
    1.87 +    SEC_OID_SECG_EC_SECP224K1,
    1.88 +    SEC_OID_SECG_EC_SECP256K1,
    1.89 +    SEC_OID_SECG_EC_SECT113R1,
    1.90 +    SEC_OID_SECG_EC_SECT113R2,
    1.91 +    SEC_OID_SECG_EC_SECT131R1,
    1.92 +    SEC_OID_SECG_EC_SECT131R2,
    1.93 +    SEC_OID_SECG_EC_SECT163R1,
    1.94 +    SEC_OID_SECG_EC_SECT193R1,
    1.95 +    SEC_OID_SECG_EC_SECT193R2,
    1.96 +    SEC_OID_SECG_EC_SECT239K1,
    1.97 +    SEC_OID_UNKNOWN	    /* ECCurve_pastLastCurve */
    1.98 +};
    1.99 +
   1.100 +typedef SECStatus (*op_func) (void *, void *, void *);
   1.101 +typedef SECStatus (*pk11_op_func) (CK_SESSION_HANDLE, void *, void *, void *);
   1.102 +
   1.103 +typedef struct ThreadDataStr {
   1.104 +    op_func op;
   1.105 +    void *p1;
   1.106 +    void *p2;
   1.107 +    void *p3;
   1.108 +    int iters;
   1.109 +    PRLock *lock;
   1.110 +    int count;
   1.111 +    SECStatus status;
   1.112 +    int isSign;
   1.113 +} ThreadData;
   1.114 +
   1.115 +void PKCS11Thread(void *data)
   1.116 +{
   1.117 +    ThreadData *threadData = (ThreadData *)data;
   1.118 +    pk11_op_func op = (pk11_op_func) threadData->op;
   1.119 +    int iters = threadData->iters;
   1.120 +    unsigned char sigData [256];
   1.121 +    SECItem sig;
   1.122 +    CK_SESSION_HANDLE session;
   1.123 +    CK_RV crv;
   1.124 +
   1.125 +    threadData->status = SECSuccess;
   1.126 +    threadData->count = 0;
   1.127 +
   1.128 +    /* get our thread's session */
   1.129 +    PR_Lock(threadData->lock);
   1.130 +    crv = NSC_OpenSession(1, CKF_SERIAL_SESSION, NULL, 0, &session);
   1.131 +    PR_Unlock(threadData->lock);
   1.132 +
   1.133 +    if (threadData->isSign) {
   1.134 +    sig.data = sigData;
   1.135 +    sig.len = sizeof(sigData);
   1.136 +    threadData->p2 = (void *)&sig;
   1.137 +    }
   1.138 + 
   1.139 +    while (iters --) {
   1.140 +    threadData->status = (*op)(session, threadData->p1, 
   1.141 +	       threadData->p2, threadData->p3);
   1.142 +    if (threadData->status != SECSuccess) {
   1.143 +	break;
   1.144 +    }
   1.145 +    threadData->count++;
   1.146 +    }
   1.147 +    return;
   1.148 +}
   1.149 +
   1.150 +void genericThread(void *data)
   1.151 +{
   1.152 +    ThreadData *threadData = (ThreadData *)data;
   1.153 +    int iters = threadData->iters;
   1.154 +    unsigned char sigData [256];
   1.155 +    SECItem sig;
   1.156 +
   1.157 +    threadData->status = SECSuccess;
   1.158 +    threadData->count = 0;
   1.159 +
   1.160 +    if (threadData->isSign) {
   1.161 +    sig.data = sigData;
   1.162 +    sig.len = sizeof(sigData);
   1.163 +    threadData->p2 = (void *)&sig;
   1.164 +    }
   1.165 + 
   1.166 +    while (iters --) {
   1.167 +    threadData->status = (*threadData->op)(threadData->p1, 
   1.168 +	       threadData->p2, threadData->p3);
   1.169 +    if (threadData->status != SECSuccess) {
   1.170 +	break;
   1.171 +    }
   1.172 +    threadData->count++;
   1.173 +    }
   1.174 +    return;
   1.175 +}
   1.176 +
   1.177 +
   1.178 +/* Time iter repetitions of operation op. */
   1.179 +SECStatus
   1.180 +M_TimeOperation(void (*threadFunc)(void *), 
   1.181 +	op_func opfunc, char *op, void *param1, void *param2, 
   1.182 +	void *param3, int iters, int numThreads, PRLock *lock, 
   1.183 +	CK_SESSION_HANDLE session, int isSign, double *rate)
   1.184 +{
   1.185 +    double dUserTime;
   1.186 +    int i, total;
   1.187 +    PRIntervalTime startTime, totalTime;
   1.188 +    PRThread **threadIDs;
   1.189 +    ThreadData *threadData;
   1.190 +    pk11_op_func pk11_op = (pk11_op_func) opfunc;
   1.191 +    SECStatus rv;
   1.192 +
   1.193 +    /* verify operation works before testing performance */
   1.194 +    if (session) {
   1.195 +	rv = (*pk11_op)(session, param1, param2, param3);
   1.196 +    } else {
   1.197 +	rv = (*opfunc)(param1, param2, param3);
   1.198 +    }
   1.199 +    if (rv != SECSuccess) {
   1.200 +	SECU_PrintError("Error:", op); 
   1.201 +	return rv;
   1.202 +    }
   1.203 +
   1.204 +    /* get Data structures */
   1.205 +    threadIDs = (PRThread **)PORT_Alloc(numThreads*sizeof(PRThread *)); 
   1.206 +    threadData = (ThreadData *)PORT_Alloc(numThreads*sizeof(ThreadData));
   1.207 +
   1.208 +    startTime = PR_Now();
   1.209 +    if (numThreads == 1) {
   1.210 +    for (i=0; i < iters; i++) {
   1.211 +	if (session) {
   1.212 +	    rv = (*pk11_op)(session, param1, param2, param3);
   1.213 +	} else {
   1.214 +	    rv = (*opfunc)(param1, param2, param3);
   1.215 +	}
   1.216 +    }
   1.217 +	total = iters;
   1.218 +    } else {
   1.219 +	for (i = 0; i < numThreads; i++) {
   1.220 +	    threadData[i].op = opfunc; 
   1.221 +	    threadData[i].p1 = (void *)param1;
   1.222 +	    threadData[i].p2 = (void *)param2;
   1.223 +	    threadData[i].p3 = (void *)param3;
   1.224 +	    threadData[i].iters = iters;
   1.225 +	    threadData[i].lock = lock;
   1.226 +	    threadData[i].isSign = isSign;
   1.227 +	    threadIDs[i] = PR_CreateThread(PR_USER_THREAD, threadFunc,
   1.228 +	                   (void *)&threadData[i], PR_PRIORITY_NORMAL,
   1.229 +	                   PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
   1.230 +	} 
   1.231 +
   1.232 +	total = 0;
   1.233 +	for (i = 0; i < numThreads; i++) {
   1.234 +	    PR_JoinThread(threadIDs[i]);
   1.235 +	    /* check the status */
   1.236 +	    total += threadData[i].count;
   1.237 +	}
   1.238 +
   1.239 +	PORT_Free(threadIDs);
   1.240 +	PORT_Free(threadData);
   1.241 +    }
   1.242 +
   1.243 +    totalTime = PR_Now()- startTime; 
   1.244 +    /* SecondsToInterval seems to be broken here ... */
   1.245 +    dUserTime = (double)totalTime/(double)1000000;
   1.246 +    if (dUserTime) {
   1.247 +	printf("    %-15s count:%4d sec: %3.2f op/sec: %6.2f\n", 
   1.248 +	    op, total, dUserTime, (double)total/dUserTime); 
   1.249 +	if (rate) {
   1.250 +	   *rate = ((double)total)/dUserTime;
   1.251 +	}
   1.252 +    }
   1.253 +    return SECSuccess;
   1.254 +}
   1.255 +
   1.256 +#define GFP_POPULATE(params,name_v) \
   1.257 +    params.name = name_v; \
   1.258 +    if ((params.name < ECCurve_noName) || \
   1.259 +	    (params.name > ECCurve_pastLastCurve)) goto cleanup; \
   1.260 +    params.type = ec_params_named; \
   1.261 +    params.curveOID.data = NULL; \
   1.262 +    params.curveOID.len = 0; \
   1.263 +    params.curve.seed.data = NULL; \
   1.264 +    params.curve.seed.len = 0; \
   1.265 +    params.DEREncoding.data = NULL; \
   1.266 +    params.DEREncoding.len = 0; \
   1.267 +    params.arena = NULL; \
   1.268 +    params.fieldID.size = ecCurve_map[name_v]->size; \
   1.269 +    params.fieldID.type = ec_field_GFp; \
   1.270 +    hexString2SECItem(params.arena, &params.fieldID.u.prime, \
   1.271 +	    ecCurve_map[name_v]->irr); \
   1.272 +    hexString2SECItem(params.arena, &params.curve.a, \
   1.273 +	    ecCurve_map[name_v]->curvea); \
   1.274 +    hexString2SECItem(params.arena, &params.curve.b, \
   1.275 +	    ecCurve_map[name_v]->curveb); \
   1.276 +    genenc[0] = '0'; \
   1.277 +    genenc[1] = '4'; \
   1.278 +    genenc[2] = '\0'; \
   1.279 +    strcat(genenc, ecCurve_map[name_v]->genx); \
   1.280 +    strcat(genenc, ecCurve_map[name_v]->geny); \
   1.281 +    hexString2SECItem(params.arena, &params.base, \
   1.282 +	    genenc); \
   1.283 +    hexString2SECItem(params.arena, &params.order, \
   1.284 +	    ecCurve_map[name_v]->order); \
   1.285 +    params.cofactor = ecCurve_map[name_v]->cofactor;
   1.286 +
   1.287 +
   1.288 +/* Test curve using specific field arithmetic. */
   1.289 +#define ECTEST_NAMED_GFP(name_c, name_v) \
   1.290 +    if (usefreebl) { \
   1.291 +	printf("Testing %s using freebl implementation...\n", name_c); \
   1.292 +	rv = ectest_curve_freebl(name_v, iterations, numThreads); \
   1.293 +	    if (rv != SECSuccess) goto cleanup; \
   1.294 +	printf("... okay.\n"); \
   1.295 +	} \
   1.296 +    if (usepkcs11) { \
   1.297 +	printf("Testing %s using pkcs11 implementation...\n", name_c); \
   1.298 +	rv = ectest_curve_pkcs11(name_v, iterations, numThreads); \
   1.299 +	    if (rv != SECSuccess) goto cleanup; \
   1.300 +	printf("... okay.\n"); \
   1.301 +     }
   1.302 +
   1.303 +/*
   1.304 + * Initializes a SECItem from a hexadecimal string
   1.305 + *
   1.306 + * Warning: This function ignores leading 00's, so any leading 00's
   1.307 + * in the hexadecimal string must be optional.
   1.308 + */
   1.309 +static SECItem *
   1.310 +hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
   1.311 +{
   1.312 +    int i = 0;
   1.313 +    int byteval = 0;
   1.314 +    int tmp = PORT_Strlen(str);
   1.315 +
   1.316 +    if ((tmp % 2) != 0) return NULL;
   1.317 +    
   1.318 +    /* skip leading 00's unless the hex string is "00" */
   1.319 +    while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
   1.320 +	str += 2;
   1.321 +	tmp -= 2;
   1.322 +    }
   1.323 +
   1.324 +    item->data = (unsigned char *) PORT_Alloc( tmp/2);
   1.325 +    if (item->data == NULL) return NULL;
   1.326 +    item->len = tmp/2;
   1.327 +
   1.328 +    while (str[i]) {
   1.329 +	if ((str[i] >= '0') && (str[i] <= '9'))
   1.330 +	    tmp = str[i] - '0';
   1.331 +	else if ((str[i] >= 'a') && (str[i] <= 'f'))
   1.332 +	    tmp = str[i] - 'a' + 10;
   1.333 +	else if ((str[i] >= 'A') && (str[i] <= 'F'))
   1.334 +	    tmp = str[i] - 'A' + 10;
   1.335 +	else
   1.336 +	    return NULL;
   1.337 +
   1.338 +	byteval = byteval * 16 + tmp;
   1.339 +	if ((i % 2) != 0) {
   1.340 +	    item->data[i/2] = byteval;
   1.341 +	    byteval = 0;
   1.342 +	}
   1.343 +	i++;
   1.344 +    }
   1.345 +
   1.346 +    return item;
   1.347 +}
   1.348 +
   1.349 +#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
   1.350 +		(x)->pValue=(v); (x)->ulValueLen = (l);
   1.351 +
   1.352 +
   1.353 +SECStatus
   1.354 +PKCS11_Derive(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey, 
   1.355 +	  CK_MECHANISM *pMech , int *dummy)
   1.356 +{
   1.357 +    CK_RV crv;
   1.358 +    CK_OBJECT_HANDLE newKey;
   1.359 +    CK_BBOOL cktrue = CK_TRUE;
   1.360 +    CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
   1.361 +    CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
   1.362 +    CK_ATTRIBUTE keyTemplate[3];
   1.363 +    CK_ATTRIBUTE *attrs = keyTemplate;
   1.364 +
   1.365 +    PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
   1.366 +    attrs++;
   1.367 +    PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
   1.368 +    attrs++;
   1.369 +    PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, 1); attrs++;
   1.370 +
   1.371 +
   1.372 +   crv = NSC_DeriveKey(session, pMech, *hKey, keyTemplate, 3, &newKey);
   1.373 +   if (crv != CKR_OK) {
   1.374 +	printf("Derive Failed CK_RV=0x%x\n", (int)crv);
   1.375 +	return SECFailure;
   1.376 +   }
   1.377 +   return SECSuccess;
   1.378 +}
   1.379 +
   1.380 +SECStatus
   1.381 +PKCS11_Sign(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey, 
   1.382 +	SECItem *sig, SECItem *digest)
   1.383 +{
   1.384 +   CK_RV crv;
   1.385 +   CK_MECHANISM mech;
   1.386 +
   1.387 +   mech.mechanism = CKM_ECDSA;
   1.388 +   mech.pParameter = NULL;
   1.389 +   mech.ulParameterLen = 0;
   1.390 +
   1.391 +   crv = NSC_SignInit(session, &mech, *hKey);
   1.392 +   if (crv != CKR_OK) {
   1.393 +    printf("Sign Failed CK_RV=0x%x\n", (int)crv);
   1.394 +    return SECFailure;
   1.395 +   }
   1.396 +   crv = NSC_Sign(session, digest->data, digest->len, sig->data, 
   1.397 +	(CK_ULONG_PTR)&sig->len);
   1.398 +   if (crv != CKR_OK) {
   1.399 +    printf("Sign Failed CK_RV=0x%x\n", (int)crv);
   1.400 +    return SECFailure;
   1.401 +   }
   1.402 +   return SECSuccess;
   1.403 +}
   1.404 +
   1.405 +SECStatus
   1.406 +PKCS11_Verify(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE *hKey, 
   1.407 +	SECItem *sig, SECItem *digest)
   1.408 +{
   1.409 +   CK_RV crv;
   1.410 +   CK_MECHANISM mech;
   1.411 +
   1.412 +   mech.mechanism = CKM_ECDSA;
   1.413 +   mech.pParameter = NULL;
   1.414 +   mech.ulParameterLen = 0;
   1.415 +
   1.416 +   crv = NSC_VerifyInit(session, &mech, *hKey);
   1.417 +   if (crv != CKR_OK) {
   1.418 +    printf("Verify Failed CK_RV=0x%x\n", (int)crv);
   1.419 +    return SECFailure;
   1.420 +   }
   1.421 +   crv = NSC_Verify(session, digest->data, digest->len, sig->data, sig->len);
   1.422 +   if (crv != CKR_OK) {
   1.423 +    printf("Verify Failed CK_RV=0x%x\n", (int)crv);
   1.424 +    return SECFailure;
   1.425 +   }
   1.426 +   return SECSuccess;
   1.427 +}
   1.428 +
   1.429 +static SECStatus
   1.430 +ecName2params(ECCurveName curve, SECKEYECParams * params)
   1.431 +{
   1.432 +    SECOidData *oidData = NULL;
   1.433 +
   1.434 +    if ((curve < ECCurve_noName) || (curve > ECCurve_pastLastCurve) ||
   1.435 +	((oidData = SECOID_FindOIDByTag(ecCurve_oid_map[curve])) == NULL)) {
   1.436 +	PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
   1.437 +	return SECFailure;
   1.438 +    }
   1.439 +
   1.440 +    SECITEM_AllocItem(NULL, params, (2 + oidData->oid.len));
   1.441 +    /*
   1.442 +     * params->data needs to contain the ASN encoding of an object ID (OID)
   1.443 +     * representing the named curve. The actual OID is in
   1.444 +     * oidData->oid.data so we simply prepend 0x06 and OID length
   1.445 +     */
   1.446 +    params->data[0] = SEC_ASN1_OBJECT_ID;
   1.447 +    params->data[1] = oidData->oid.len;
   1.448 +    memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
   1.449 +
   1.450 +    return SECSuccess;
   1.451 +}
   1.452 +
   1.453 +
   1.454 +
   1.455 +/* Performs basic tests of elliptic curve cryptography over prime fields.
   1.456 + * If tests fail, then it prints an error message, aborts, and returns an
   1.457 + * error code. Otherwise, returns 0. */
   1.458 +SECStatus
   1.459 +ectest_curve_pkcs11(ECCurveName curve, int iterations, int numThreads)
   1.460 +{
   1.461 +    CK_OBJECT_HANDLE ecPriv;
   1.462 +    CK_OBJECT_HANDLE ecPub;
   1.463 +    CK_SESSION_HANDLE session;
   1.464 +    SECItem sig;
   1.465 +    SECItem digest;
   1.466 +    SECKEYECParams ecParams;
   1.467 +    CK_MECHANISM mech;
   1.468 +    CK_ECDH1_DERIVE_PARAMS ecdh_params;
   1.469 +    unsigned char sigData [256];
   1.470 +    unsigned char digestData[20];
   1.471 +    unsigned char pubKeyData[256];
   1.472 +    PRLock *lock = NULL;
   1.473 +    double signRate, deriveRate;
   1.474 +    CK_ATTRIBUTE template;
   1.475 +    SECStatus rv;
   1.476 +    CK_RV crv;
   1.477 +
   1.478 +    ecParams.data = NULL;
   1.479 +    ecParams.len = 0;
   1.480 +    rv = ecName2params(curve, &ecParams);
   1.481 +    if (rv != SECSuccess) {
   1.482 +    goto cleanup;
   1.483 +    }
   1.484 +
   1.485 +    crv = NSC_OpenSession(1, CKF_SERIAL_SESSION, NULL, 0, &session);
   1.486 +    if (crv != CKR_OK) {
   1.487 +    printf("OpenSession Failed CK_RV=0x%x\n", (int)crv);
   1.488 +    return SECFailure;
   1.489 +    }
   1.490 +
   1.491 +    PORT_Memset(digestData, 0xa5, sizeof(digestData));
   1.492 +    digest.data = digestData;
   1.493 +    digest.len = sizeof(digestData);
   1.494 +    sig.data = sigData;
   1.495 +    sig.len = sizeof(sigData);
   1.496 +
   1.497 +    template.type = CKA_EC_PARAMS;
   1.498 +    template.pValue = ecParams.data;
   1.499 +    template.ulValueLen = ecParams.len;
   1.500 +    mech.mechanism = CKM_EC_KEY_PAIR_GEN;
   1.501 +    mech.pParameter = NULL;
   1.502 +    mech.ulParameterLen = 0;
   1.503 +    crv = NSC_GenerateKeyPair(session, &mech, 
   1.504 +		  &template, 1, NULL, 0, &ecPub, &ecPriv);
   1.505 +    if (crv != CKR_OK) {
   1.506 +    printf("GenerateKeyPair Failed CK_RV=0x%x\n", (int)crv);
   1.507 +    return SECFailure;
   1.508 +    }
   1.509 +
   1.510 +    template.type = CKA_EC_POINT;
   1.511 +    template.pValue = pubKeyData;
   1.512 +    template.ulValueLen = sizeof(pubKeyData);
   1.513 +    crv = NSC_GetAttributeValue(session, ecPub, &template, 1);
   1.514 +    if (crv != CKR_OK) {
   1.515 +    printf("GenerateKeyPair Failed CK_RV=0x%x\n", (int)crv);
   1.516 +    return SECFailure;
   1.517 +    }
   1.518 +
   1.519 +    ecdh_params.kdf = CKD_NULL;
   1.520 +    ecdh_params.ulSharedDataLen = 0;
   1.521 +    ecdh_params.pSharedData = NULL;
   1.522 +    ecdh_params.ulPublicDataLen = template.ulValueLen;
   1.523 +    ecdh_params.pPublicData = template.pValue;
   1.524 +
   1.525 +    mech.mechanism = CKM_ECDH1_DERIVE;
   1.526 +    mech.pParameter = (void *)&ecdh_params;
   1.527 +    mech.ulParameterLen = sizeof(ecdh_params);
   1.528 +
   1.529 +    lock = PR_NewLock();
   1.530 +
   1.531 +    rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Derive, "ECDH_Derive",
   1.532 +	    &ecPriv, &mech,  NULL, iterations, numThreads, 
   1.533 +	    lock, session, 0, &deriveRate);
   1.534 +    if (rv != SECSuccess) goto cleanup;
   1.535 +    rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Sign, "ECDSA_Sign",
   1.536 +	    (void *)&ecPriv, &sig, &digest, iterations, numThreads,
   1.537 +	    lock, session, 1, &signRate);
   1.538 +    if (rv != SECSuccess) goto cleanup;
   1.539 +    printf("        ECDHE max rate = %.2f\n", (deriveRate+signRate)/4.0);
   1.540 +    /* get a signature */
   1.541 +    rv = PKCS11_Sign(session, &ecPriv, &sig, &digest);
   1.542 +    if (rv != SECSuccess) goto cleanup;
   1.543 +    rv = M_TimeOperation(PKCS11Thread, (op_func)PKCS11_Verify, "ECDSA_Verify",
   1.544 +	    (void *)&ecPub, &sig, &digest, iterations, numThreads,
   1.545 +	    lock, session, 0, NULL);
   1.546 +    if (rv != SECSuccess) goto cleanup;
   1.547 +
   1.548 +cleanup:
   1.549 +    if (lock) {
   1.550 +    PR_DestroyLock(lock);
   1.551 +    }
   1.552 +    return rv;
   1.553 +}
   1.554 +
   1.555 +SECStatus
   1.556 +ECDH_DeriveWrap(ECPrivateKey *priv, ECPublicKey *pub, int *dummy)
   1.557 +{
   1.558 +    SECItem secret;
   1.559 +    unsigned char secretData[256];
   1.560 +    SECStatus rv;
   1.561 +
   1.562 +    secret.data = secretData;
   1.563 +    secret.len = sizeof(secretData);
   1.564 +
   1.565 +    rv = ECDH_Derive(&pub->publicValue, &pub->ecParams, 
   1.566 +	&priv->privateValue, 0, &secret);
   1.567 +#ifdef notdef
   1.568 +    if (rv == SECSuccess) {
   1.569 +    PORT_Free(secret.data);
   1.570 +    }
   1.571 +#endif
   1.572 +    return rv;
   1.573 +}
   1.574 +
   1.575 +/* Performs basic tests of elliptic curve cryptography over prime fields.
   1.576 + * If tests fail, then it prints an error message, aborts, and returns an
   1.577 + * error code. Otherwise, returns 0. */
   1.578 +SECStatus
   1.579 +ectest_curve_freebl(ECCurveName curve, int iterations, int numThreads)
   1.580 +{
   1.581 +    ECParams      ecParams;
   1.582 +    ECPrivateKey *ecPriv = NULL;
   1.583 +    ECPublicKey ecPub;
   1.584 +    SECItem sig;
   1.585 +    SECItem digest;
   1.586 +    unsigned char sigData [256];
   1.587 +    unsigned char digestData[20];
   1.588 +    double signRate, deriveRate;
   1.589 +    char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
   1.590 +    SECStatus rv;
   1.591 +
   1.592 +
   1.593 +    GFP_POPULATE(ecParams, curve);
   1.594 +
   1.595 +    PORT_Memset(digestData, 0xa5, sizeof(digestData));
   1.596 +    digest.data = digestData;
   1.597 +    digest.len = sizeof(digestData);
   1.598 +    sig.data = sigData;
   1.599 +    sig.len = sizeof(sigData);
   1.600 +
   1.601 +    rv = EC_NewKey(&ecParams, &ecPriv);
   1.602 +    if (rv != SECSuccess) {
   1.603 +    return SECFailure;
   1.604 +    }
   1.605 +    ecPub.ecParams = ecParams;
   1.606 +    ecPub.publicValue = ecPriv->publicValue;
   1.607 +
   1.608 +    M_TimeOperation(genericThread, (op_func) ECDH_DeriveWrap, "ECDH_Derive",
   1.609 +	    ecPriv, &ecPub, NULL, iterations, numThreads, 0, 0, 0, &deriveRate);
   1.610 +    if (rv != SECSuccess) goto cleanup;
   1.611 +    M_TimeOperation(genericThread, (op_func) ECDSA_SignDigest, "ECDSA_Sign",
   1.612 +	    ecPriv, &sig, &digest, iterations, numThreads, 0, 0, 1, &signRate);
   1.613 +    if (rv != SECSuccess) goto cleanup;
   1.614 +    printf("        ECDHE max rate = %.2f\n", (deriveRate+signRate)/4.0);
   1.615 +    rv = ECDSA_SignDigest(ecPriv, &sig, &digest);
   1.616 +    if (rv != SECSuccess) goto cleanup;
   1.617 +    M_TimeOperation(genericThread, (op_func) ECDSA_VerifyDigest, "ECDSA_Verify",
   1.618 +	    &ecPub, &sig, &digest, iterations, numThreads, 0, 0, 0, NULL);
   1.619 +    if (rv != SECSuccess) goto cleanup;
   1.620 +
   1.621 +cleanup:
   1.622 +    return rv;
   1.623 +}
   1.624 +
   1.625 +/* Prints help information. */
   1.626 +void
   1.627 +printUsage(char *prog)
   1.628 +{
   1.629 +    printf("Usage: %s [-i iterations] [-t threads ] [-ans] [-fp] [-A]\n",prog);
   1.630 +}
   1.631 +
   1.632 +/* Performs tests of elliptic curve cryptography over prime fields If
   1.633 + * tests fail, then it prints an error message, aborts, and returns an
   1.634 + * error code. Otherwise, returns 0. */
   1.635 +int
   1.636 +main(int argv, char **argc)
   1.637 +{
   1.638 +    int ansi = 0;
   1.639 +    int nist = 0;
   1.640 +    int secp = 0;
   1.641 +    int usefreebl = 0;
   1.642 +    int usepkcs11 = 0;
   1.643 +    int i;
   1.644 +    SECStatus rv = SECSuccess;
   1.645 +    int iterations = 100;
   1.646 +    int numThreads = 1;
   1.647 +
   1.648 +    /* read command-line arguments */
   1.649 +    for (i = 1; i < argv; i++) {
   1.650 +	if (strcasecmp(argc[i], "-i") == 0) {
   1.651 +	    i++;
   1.652 +	    iterations = atoi(argc[i]);
   1.653 +	} else if (strcasecmp(argc[i], "-t") == 0) {
   1.654 +	    i++;
   1.655 +	    numThreads = atoi(argc[i]);
   1.656 +	} else if (strcasecmp(argc[i], "-A") == 0) {
   1.657 +	    ansi = nist = secp = 1;
   1.658 +	    usepkcs11 = usefreebl = 1;
   1.659 +	} else if (strcasecmp(argc[i], "-a") == 0) {
   1.660 +	    ansi = 1;
   1.661 +	} else if (strcasecmp(argc[i], "-n") == 0) {
   1.662 +	    nist = 1;
   1.663 +	} else if (strcasecmp(argc[i], "-s") == 0) {
   1.664 +	    secp = 1;
   1.665 +	} else if (strcasecmp(argc[i], "-p") == 0) {
   1.666 +	    usepkcs11 = 1;
   1.667 +	} else if (strcasecmp(argc[i], "-f") == 0) {
   1.668 +	    usefreebl = 1;
   1.669 +	} else {
   1.670 +	    printUsage(argc[0]);
   1.671 +	    return 0;
   1.672 +	}
   1.673 +    }
   1.674 +
   1.675 +    if ((ansi | nist | secp) == 0) {
   1.676 +	nist = 1;
   1.677 +    }
   1.678 +    if ((usepkcs11|usefreebl) == 0) {
   1.679 +	usefreebl = 1;
   1.680 +    }
   1.681 +
   1.682 +    rv = NSS_NoDB_Init(NULL);
   1.683 +    if (rv != SECSuccess) {
   1.684 +	SECU_PrintError("Error:", "NSS_NoDB_Init"); 
   1.685 +	goto cleanup;
   1.686 +    }
   1.687 +
   1.688 +    /* specific arithmetic tests */
   1.689 +    if (nist) {
   1.690 +        ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
   1.691 +        ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192);
   1.692 +        ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224);
   1.693 +        ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
   1.694 +        ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
   1.695 +        ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
   1.696 +    }
   1.697 +    if (ansi) {
   1.698 +        ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1);
   1.699 +        ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2);
   1.700 +        ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3);
   1.701 +        ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1);
   1.702 +        ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2);
   1.703 +        ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3);
   1.704 +        ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1);
   1.705 +    }
   1.706 +    if (secp) {
   1.707 +        ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1);
   1.708 +        ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2);
   1.709 +        ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1);
   1.710 +        ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2);
   1.711 +        ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
   1.712 +        ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
   1.713 +        ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2);
   1.714 +        ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1);
   1.715 +        ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1);
   1.716 +        ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1);
   1.717 +        ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1);
   1.718 +        ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1);
   1.719 +        ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1);
   1.720 +        ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1);
   1.721 +        ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1);
   1.722 +    }
   1.723 +
   1.724 +  cleanup:
   1.725 +    if (rv != SECSuccess) {
   1.726 +	printf("Error: exiting with error value\n");
   1.727 +    }
   1.728 +    return rv;
   1.729 +}

mercurial