The TMS infrastructure was initially created with only RSA in mind. This task specifically deals with adding initial ECC support for TMS. It will support basic token enrollment both with client-side and server-side key generation, as well as key archival (minus key injection, which is task #235).
TPS ECC infrastructure TPS-ECC.patch2
addressed review comments. TPS-ECC.forReview2
RHCS8.1 Errata checkin
base]$ svn commit Enter passphrase for key '/home/cfu/.ssh/id_rsa': Sending base/common/src/com/netscape/certsrv/request/IRequest.java Sending base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java Sending base/kra/src/com/netscape/kra/NetkeyKeygenService.java Sending base/tps/src/channel/Secure_Channel.cpp Sending base/tps/src/cms/CertEnroll.cpp Sending base/tps/src/engine/RA.cpp Sending base/tps/src/include/channel/Secure_Channel.h Sending base/tps/src/include/cms/CertEnroll.h Sending base/tps/src/include/engine/RA.h Sending base/tps/src/include/main/Buffer.h Sending base/tps/src/include/processor/RA_Enroll_Processor.h Sending base/tps/src/main/Buffer.cpp Sending base/tps/src/main/ObjectSpec.cpp Sending base/tps/src/processor/RA_Enroll_Processor.cpp Transmitting file data .............. Committed revision 2491.
RHCS82 checkin
base]$ svn commit Enter passphrase for key '/home/cfu/.ssh/id_rsa': Sending base/common/src/com/netscape/certsrv/request/IRequest.java Sending base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java Sending base/kra/src/com/netscape/kra/NetkeyKeygenService.java Sending base/tps/src/channel/Secure_Channel.cpp Sending base/tps/src/cms/CertEnroll.cpp Sending base/tps/src/engine/RA.cpp Sending base/tps/src/include/channel/Secure_Channel.h Sending base/tps/src/include/cms/CertEnroll.h Sending base/tps/src/include/engine/RA.h Sending base/tps/src/include/main/Buffer.h Sending base/tps/src/include/processor/RA_Enroll_Processor.h Sending base/tps/src/main/Buffer.cpp Sending base/tps/src/main/ObjectSpec.cpp Sending base/tps/src/processor/RA_Enroll_Processor.cpp Transmitting file data .............. Committed revision 2492.
DOGTAG_9_BRANCH checkin
pki]$ git push Enter passphrase for key '/home/cfu/.ssh/id_rsa': Counting objects: 86, done. Compressing objects: 100% (40/40), done. Writing objects: 100% (44/44), 12.10 KiB, done. Total 44 (delta 32), reused 0 (delta 0) To ssh://git.fedorahosted.org/git/pki.git 809c5f8..4e7bb35 DOGTAG_9_BRANCH -> DOGTAG_9_BRANCH
dogtag10 checkin
pki]$ git push Counting objects: 92, done. Compressing objects: 100% (46/46), done. Writing objects: 100% (50/50), 12.19 KiB, done. Total 50 (delta 38), reused 0 (delta 0) To ssh://cfu@git.fedorahosted.org/git/pki.git 8ed86a7..e689561 master -> master
example tpsclient enrollment config file enroll.tps.ec
example ECC format config file for tpsclient format.tps.ec.7994
example tokenname file (contains ECC token name, like certicom) tokenname
CS.cfg sample for client-side key generation CS.cfg.clientSideKeyGenEC
CS.cfg example for ECC server-side key generation CS.cfg.serverSideKeyGenEC
CS.cfg example for ECC key recovery CS.cfg.recoveryECC
(for reference) CS.cfg example for RSA server-side key generation CS.cfg.serverSideKeyGenRSA
Metadata Update from @cfu: - Issue assigned to cfu - Issue set to the milestone: ECC Effort
Two initial attachments: * TPS-ECC.patch2 (72.8 KB) - added by cfu 4 years ago. TPS ECC infrastructure * TPS-ECC.forReview2 (73.6 KB) - added by cfu 4 years ago. addressed review comments.
Metadata Update from @mharmsen: - Custom field feature adjusted to '' - Custom field origin adjusted to Community - Custom field proposedmilestone adjusted to '' - Custom field proposedpriority adjusted to '' - Custom field reviewer adjusted to '' - Custom field version adjusted to '' - Issue close_status updated to: None (was: Fixed)
TPS-ECC.patch2
Index: common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java 2 =================================================================== 3 --- common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java (revision 2471) 4 +++ common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java (working copy) 5 @@ -74,6 +74,7 @@ 6 CMS.getSubsystem(authority); 7 8 mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); 9 + 10 } 11 12 / 13 @@ -110,11 +111,23 @@ 14 15 CMS.debug("processServerSideKeyGen begins:"); 16 17 + // supported EC cuves by the smart cards 18 + String curveList = sconfig.getString("kra.keygen.curvelist" 19 + "nistp256,nistp384,nistp521"); 20 + StringTokenizer st = new StringTokenizer(curveList, ","); 21 + int num = st.contTokens(); 22 + String[] supportedECCurves = new String[num]; 23 + for (int i=0; i< num; i++) { 24 + supportedECCurves[i] = st.nextToken(); 25 + } 26 + 27 String rCUID = req.getParameter("CUID"); 28 String rUserid = req.getParameter("userid"); 29 String rdesKeyString = req.getParameter("drm_trans_desKey"); 30 - String rArchive = req.getParameter("archive"); 31 - String rKeysize = req.getParameter("keysize"); 32 + String rArchive = req.getParameter("archive"); 33 + String rKeysize = req.getParameter("keysize"); 34 + String rKeytype = req.getParameter("keytype"); 35 + String rKeycurve = req.getParameter("eckeycurve"); 36 37 if ((rCUID == null) || (rCUID.equals(""))) { 38 CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: CUID"); 39 @@ -126,10 +139,35 @@ 40 missingParam = true; 41 } 42 43 - if ((rKeysize == null) || (rKeysize.equals(""))) { 44 - rKeysize = "1024"; // default to 1024 45 - } 46 + // keysize is for non-EC (EC uses keycurve) 47 + if ((!rKeytype.equals("EC") && (rKeysize == null) || (rKeysize.equals(""))) { 48 + rKeysize = "1024"; // default to 1024 49 + } 50 51 + // if not specified, default to RSA 52 + if ((rKeytype == null) || (rKeytype.equals(""))) { 53 + rKeytype = "RSA"; 54 + } 55 + 56 + if (rKeytype.equals("EC")) { 57 + if ((rKeycurve == null) || (rKeycurve.equals(""))) { 58 + rKeycurve = "nistp256"; 59 + } 60 + // is the specified curve supported? 61 + boolean isSupportedCurve = false; 62 + for (int i=0; i80 if ((rArchive == null) || (rArchive.equals(""))) { 81 CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing key archival flag 'archive' ,default to true"); 82 - rArchive = "true"; 83 + rArchive = "true"; 84 } 85 86 String selectedToken = null; 87 @@ -150,17 +188,19 @@ 88 thisreq.setExtData(IRequest.NETKEY_ATTR_CUID, rCUID); 89 thisreq.setExtData(IRequest.NETKEY_ATTR_USERID, rUserid); 90 thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, rdesKeyString); 91 - thisreq.setExtData(IRequest.NETKEY_ATTR_ARCHIVE_FLAG, rArchive); 92 - thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_SIZE, rKeysize); 93 + thisreq.setExtData(IRequest.NETKEY_ATTR_ARCHIVE_FLAG, rArchive); 94 + thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_SIZE, rKeysize); 95 + thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_TYPE, rKeytype); 96 + thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_EC_CURVE, rKeycurve); 97 98 queue.processRequest( thisreq ); 99 Integer result = thisreq.getExtDataInInteger(IRequest.RESULT); 100 if (result != null) { 101 - // sighs! tps thinks 0 is good, and DRM thinks 1 is good 102 - if (result.intValue() == 1) 103 - status = "0"; 104 - else 105 - status = result.toString(); 106 + // sighs! tps thinks 0 is good, and DRM thinks 1 is good 107 + if (result.intValue() == 1) 108 + status = "0"; 109 + else 110 + status = result.toString(); 111 } else 112 status = "7"; 113114 @@ -183,7 +223,7 @@ 115 publicKeyString = thisreq.getExtDataInString("public_key"); 116 wrappedPrivKeyString = thisreq.getExtDataInString("wrappedUserPrivate"); 117118 - String ivString = thisreq.getExtDataInString("iv_s"); 119 + String ivString = thisreq.getExtDataInString("iv_s"); 120121 /* 122 if (selectedToken == null) 123 @@ -194,12 +234,12 @@ 124 else { 125 StringBuffer sb = new StringBuffer(); 126 sb.append("status=0&"); 127 - sb.append("wrapped_priv_key="); 128 - sb.append(wrappedPrivKeyString); 129 - sb.append("&iv_param="); 130 - sb.append(ivString); 131 + sb.append("wrapped_priv_key="); 132 + sb.append(wrappedPrivKeyString); 133 + sb.append("&iv_param="); 134 + sb.append(ivString); 135 sb.append("&public_key="); 136 - sb.append(publicKeyString); 137 + sb.append(publicKeyString); 138 value = sb.toString(); 139140 } 141 @@ -267,9 +307,9 @@ 142 } 143144 // begin Netkey serverSideKeyGen and archival 145 - CMS.debug("GenerateKeyPairServlet: processServerSideKeyGen would be called"); 146 - processServerSideKeyGen(req, resp); 147 - return; 148 + CMS.debug("GenerateKeyPairServlet: processServerSideKeyGen would be called"); 149 + processServerSideKeyGen(req, resp); 150 + return; 151 // end Netkey functions 152153 } 154 Index: common/src/com/netscape/certsrv/request/IRequest.java 155 =================================================================== 156 --- common/src/com/netscape/certsrv/request/IRequest.java (revision 2471) 157 +++ common/src/com/netscape/certsrv/request/IRequest.java (working copy) 158 @@ -153,6 +153,8 @@ 159 public final static String NETKEY_ATTR_ENC_PRIVKEY_FLAG ="encryptPrivKey"; 160 public final static String NETKEY_ATTR_USER_CERT = "cert"; 161 public final static String NETKEY_ATTR_KEY_SIZE = "keysize"; 162 + public final static String NETKEY_ATTR_KEY_TYPE = "keytype"; 163 + public final static String NETKEY_ATTR_KEY_EC_CURVE = "eckeycurve"; 164165 // requestor type values. 166 public static final String REQUESTOR_EE = "EE"; 167 Index: tps/src/processor/RA_Enroll_Processor.cpp 168 =================================================================== 169 --- tps/src/processor/RA_Enroll_Processor.cpp (revision 2471) 170 +++ tps/src/processor/RA_Enroll_Processor.cpp (working copy) 171 @@ -184,7 +184,7 @@ 172 const char *cert_attr_id, 173 const char *pri_attr_id, 174 const char *pub_attr_id, 175 - BYTE se_p1, BYTE se_p2, int keysize, const char *connid, const char *keyTypePrefix,char * applet_version) 176 + BYTE se_p1, BYTE se_p2, BYTE algorithm, int keysize, const char *connid, const char *keyTypePrefix,char * applet_version) 177 { 178 RA_Status status = STATUS_NO_ERROR; 179 int rc = -1; 180 @@ -231,6 +231,9 @@ 181 RA::Debug(LL_PER_CONNECTION,FN, 182 "Start of keygen/certificate enrollment"); 183184 + bool isECC = RA::isAlgorithmECC(algorithm); 185 + SECKEYECParams *eccParams = NULL; 186 + 187 // get key version for audit logs 188 if (channel != NULL) { 189 if( keyVersion != NULL ) { 190 @@ -288,8 +291,8 @@ 191 (progress_block_size * 15/100) /* progress */, 192 "PROGRESS_KEY_GENERATION"); 193194 - if (key_type == KEY_TYPE_ENCRYPTION) {// do serverSide keygen? 195 - 196 + if (key_type == KEY_TYPE_ENCRYPTION) { 197 + // do serverSide keygen? 198 PR_snprintf((char *)configname, 256, "%s.serverKeygen.enable", keyTypePrefix); 199 RA::Debug(LL_PER_CONNECTION,FN, 200 "looking for config %s", configname); 201 @@ -300,57 +303,56 @@ 202203 if (serverKeygen) { 204 RA::Debug(LL_PER_CONNECTION,FN, 205 - "Private key is to be generated on server"); 206 + "Private key is to be generated on server"); 207208 PR_snprintf((char *)configname, 256, "%s.serverKeygen.drm.conn", keyTypePrefix); 209 RA::Debug(LL_PER_CONNECTION,FN, 210 - "looking for config %s", configname); 211 + "looking for config %s", configname); 212 drmconnid = RA::GetConfigStore()->GetConfigAsString(configname); 213 214 PR_snprintf((char )configname, 256, "%s.serverKeygen.archive", keyTypePrefix); 215 bool archive = RA::GetConfigStore()->GetConfigAsBool(configname, true); 216 217 RA::Debug(LL_PER_CONNECTION,FN, 218 - "calling ServerSideKeyGen with userid =%s, archive=%s", userid, archive? "true":"false"); 219 + "calling ServerSideKeyGen with userid =%s, archive=%s", userid, archive? "true":"false"); 220 221 RA::ServerSideKeyGen(session, cuid, userid, 222 channel->getDrmWrappedDESKey(), &pKey, 223 &wrappedPrivKey, &ivParam, drmconnid, 224 - archive, keysize); 225 + archive, keysize, isECC); 226 227 if (pKey == NULL) { 228 - RA::Error(LL_PER_CONNECTION,FN, 229 - "Failed to generate key on server. Please check DRM."); 230 - RA::Debug(LL_PER_CONNECTION,FN, 231 - "ServerSideKeyGen called, pKey is NULL"); 232 - status = STATUS_ERROR_MAC_ENROLL_PDU; 233 + RA::Error(LL_PER_CONNECTION,FN, 234 + "Failed to generate key on server. Please check DRM."); 235 + RA::Debug(LL_PER_CONNECTION,FN, 236 + "ServerSideKeyGen called, pKey is NULL"); 237 + status = STATUS_ERROR_MAC_ENROLL_PDU; 238 239 PR_snprintf(audit_msg, 512, "ServerSideKeyGen called, failed to generate key on server"); 240 - goto loser; 241 + goto loser; 242 } else 243 - RA::Debug(LL_PER_CONNECTION,FN, 244 - "key value = %s", pKey); 245 + RA::Debug(LL_PER_CONNECTION,FN, 246 + "key value = %s", pKey); 247 248 249 if (wrappedPrivKey == NULL) { 250 - RA::Debug(LL_PER_CONNECTION,FN, 251 - "ServerSideKeyGen called, wrappedPrivKey is NULL"); 252 - status = STATUS_ERROR_MAC_ENROLL_PDU; 253 + RA::Debug(LL_PER_CONNECTION,FN, 254 + "ServerSideKeyGen called, wrappedPrivKey is NULL"); 255 + status = STATUS_ERROR_MAC_ENROLL_PDU; 256 PR_snprintf(audit_msg, 512, "ServerSideKeyGen called, wrappedPrivKey is NULL"); 257 - goto loser; 258 + goto loser; 259 } else 260 - RA::Debug(LL_PER_CONNECTION,FN, 261 - "wrappedPrivKey = %s", wrappedPrivKey); 262 + RA::Debug(LL_PER_CONNECTION,FN, 263 + "wrappedPrivKey = %s", wrappedPrivKey); 264 265 if (ivParam == NULL) { 266 - RA::Debug(LL_PER_CONNECTION,FN, 267 - "ServerSideKeyGen called, ivParam is NULL"); 268 - status = STATUS_ERROR_MAC_ENROLL_PDU; 269 + RA::Debug(LL_PER_CONNECTION,FN, 270 + "ServerSideKeyGen called, ivParam is NULL"); 271 + status = STATUS_ERROR_MAC_ENROLL_PDU; 272 PR_snprintf(audit_msg, 512, "ServerSideKeyGen called, ivParam is NULL"); 273 - goto loser; 274 + goto loser; 275 } else 276 - RA::Debug(LL_PER_CONNECTION,FN, 277 - "ivParam = %s", ivParam); 278 + RA::Debug(LL_PER_CONNECTION,FN, "ivParam = %s", ivParam); 279 280 / 281 * the following code converts b64-encoded public key info into SECKEYPublicKey 282 @@ -359,39 +361,40 @@ 283 SECItem der; 284 CERTSubjectPublicKeyInfo spki = NULL; 285 286 + Buffer decodePubKey = Util::URLDecode(pKey); 287 + char pKey_ascii = 288 + BTOA_DataToAscii(decodePubKey->getBuf(), decodePubKey->getLen()); 289 + 290 der.type = (SECItemType) 0; / initialize it, since convertAsciiToItem does not set it / 291 - rv = ATOB_ConvertAsciiToItem (&der, pKey); 292 + rv = ATOB_ConvertAsciiToItem (&der, pKey_ascii); 293 if (rv != SECSuccess){ 294 - RA::Debug(LL_PER_CONNECTION,FN, 295 - "failed to convert b64 private key to binary"); 296 - SECITEM_FreeItem(&der, PR_FALSE); 297 - status = STATUS_ERROR_MAC_ENROLL_PDU; 298 - PR_snprintf(audit_msg, 512, "ServerSideKeyGen: failed to convert b64 private key to binary"); 299 - goto loser; 300 - }else { 301 - RA::Debug(LL_PER_CONNECTION,FN, 302 - "decoded private key as: secitem (len=%d)",der.len); 303 + RA::Debug(LL_PER_CONNECTION,FN, 304 + "failed to convert b64 private key to binary"); 305 + SECITEM_FreeItem(&der, PR_FALSE); 306 + status = STATUS_ERROR_MAC_ENROLL_PDU; 307 + PR_snprintf(audit_msg, 512, "ServerSideKeyGen: failed to convert b64 private key to binary"); 308 + goto loser; 309 + } else { 310 + RA::Debug(LL_PER_CONNECTION,FN, 311 + "decoded private key as: secitem (len=%d)",der.len); 312 313 - spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der); 314 + spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der); 315 316 - if (spki != NULL) { 317 - RA::Debug(LL_PER_CONNECTION,FN, 318 - "Successfully decoded DER SubjectPublicKeyInfo structure"); 319 - pk_p = SECKEY_ExtractPublicKey(spki); 320 - if (pk_p != NULL) 321 - RA::Debug(LL_PER_CONNECTION,FN, 322 - "Successfully extracted public key from SPKI structure"); 323 - else 324 - RA::Debug(LL_PER_CONNECTION,FN, 325 - "Failed to extract public key from SPKI"); 326 - } else { 327 - RA::Debug(LL_PER_CONNECTION,FN, 328 - "Failed to decode SPKI structure"); 329 - } 330 + if (spki != NULL) { 331 + RA::Debug(LL_PER_CONNECTION,FN, 332 + "Successfully decoded DER SubjectPublicKeyInfo structure"); 333 + pk_p = SECKEY_ExtractPublicKey(spki); 334 + if (pk_p != NULL) 335 + RA::Debug(LL_PER_CONNECTION,FN, "Successfully extracted public key from SPKI structure"); 336 + else 337 + RA::Debug(LL_PER_CONNECTION,FN, "Failed to extract public key from SPKI"); 338 + } else { 339 + RA::Debug(LL_PER_CONNECTION,FN, 340 + "Failed to decode SPKI structure"); 341 + } 342 343 - SECITEM_FreeItem(&der, PR_FALSE); 344 - SECKEY_DestroySubjectPublicKeyInfo(spki); 345 - 346 + SECITEM_FreeItem(&der, PR_FALSE); 347 + SECKEY_DestroySubjectPublicKeyInfo(spki); 348 } 349 350 } else { //generate keys on token 351 @@ -404,6 +407,12 @@ 352 if(key_check && key_check->size()) 353 alg = 0x81; 354 355 + 356 + if (isECC) { 357 + alg = algorithm; 358 + } 359 + 360 + 361 len = channel->StartEnrollment( 362 se_p1, se_p2, 363 wrapped_challenge, 364 @@ -460,6 +469,8 @@ 365 plaintext_challenge); 366 367 368 + // We have received the public key blob for ECC 369 + 370 // send status update to the client 371 StatusUpdate(session, extensions, 372 start_progress + (index * progress_block_size) + 373 @@ -471,7 +482,7 @@ 374 375 pk_p = certEnroll->ParsePublicKeyBlob( 376 (unsigned char )(BYTE )public_key /blob/, 377 - plaintext_challenge); 378 + plaintext_challenge, isECC); 379 380 if (pk_p == NULL) { 381 RA::Error(LL_PER_CONNECTION,FN, 382 @@ -550,8 +561,10 @@ 383 goto loser; 384 } 385 386 - si_mod = pk_p->u.rsa.modulus; 387 - modulus = new Buffer((BYTE) si_mod.data, si_mod.len); 388 + if (!isECC) { 389 + si_mod = pk_p->u.rsa.modulus; 390 + modulus = new Buffer((BYTE) si_mod.data, si_mod.len); 391 + } 392 393 / 394 * RFC 3279 395 @@ -569,15 +582,15 @@ 396 si_kid = PK11_MakeIDFromPubKey(&spkix->subjectPublicKey); 397 spkix->subjectPublicKey.len <<= 3; 398 399 - 400 keyid = new Buffer((BYTE) si_kid->data, si_kid->len); 401 402 - si_exp = pk_p->u.rsa.publicExponent; 403 - exponent = new Buffer((BYTE) si_exp.data, si_exp.len); 404 + if (!isECC) { 405 + si_exp = pk_p->u.rsa.publicExponent; 406 + exponent = new Buffer((BYTE) si_exp.data, si_exp.len); 407 + RA::Debug(LL_PER_CONNECTION,FN, 408 + "Keyid, modulus and exponent have been extracted from public key"); 409 + } 410 411 - RA::Debug(LL_PER_CONNECTION,FN, 412 - "Keyid, modulus and exponent have been extracted from public key"); 413 - 414 SECKEY_DestroySubjectPublicKeyInfo(spkix); 415 416 cert_string = (char ) cert->string(); 417 @@ -788,67 +801,77 @@ 418 419 / write certificate from CA to netkey / 420 if (pkcs11obj_enable) { 421 - ObjectSpec objSpec = 422 - ObjectSpec::ParseFromTokenData( 423 - (cert_id[0] << 24) + 424 - (cert_id[1] << 16), 425 - cert); 426 - pkcs_objx->AddObjectSpec(objSpec); 427 + ObjectSpec objSpec = 428 + ObjectSpec::ParseFromTokenData( 429 + (cert_id[0] << 24) + 430 + (cert_id[1] << 16), 431 + cert); 432 + pkcs_objx->AddObjectSpec(objSpec); 433 } else { 434 - RA::Debug(LL_PER_CONNECTION,FN, 435 - "About to create certificate object on token"); 436 - rc = channel->CreateCertificate(cert_id, cert); 437 - if (rc == -1) { 438 - RA::Error(LL_PER_CONNECTION,FN, 439 - "Failed to create certificate object on token"); 440 - status = STATUS_ERROR_MAC_ENROLL_PDU; 441 - PR_snprintf(audit_msg, 512, "Failed to create certificate object on token"); 442 - goto loser; 443 - } 444 + RA::Debug(LL_PER_CONNECTION,FN, 445 + "About to create certificate object on token"); 446 + rc = channel->CreateCertificate(cert_id, cert); 447 + if (rc == -1) { 448 + RA::Error(LL_PER_CONNECTION,FN, 449 + "Failed to create certificate object on token"); 450 + status = STATUS_ERROR_MAC_ENROLL_PDU; 451 + PR_snprintf(audit_msg, 512, "Failed to create certificate object on token"); 452 + goto loser; 453 + } 454 } 455 456 // build label 457 PR_snprintf((char )configname, 256, "%s.%s.keyGen.%s.label", 458 - OP_PREFIX, tokenType, keyType); 459 + OP_PREFIX, tokenType, keyType); 460 RA::Debug(LL_PER_CONNECTION,FN, 461 - "label '%s'", configname); 462 + "label '%s'", configname); 463 pattern = RA::GetConfigStore()->GetConfigAsString(configname); 464 label = MapPattern(&nv, (char ) pattern); 465 466 if (pkcs11obj_enable) { 467 - Buffer b = channel->CreatePKCS11CertAttrsBuffer( 468 - key_type, cert_attr_id, label, keyid); 469 - ObjectSpec objSpec = 470 - ObjectSpec::ParseFromTokenData( 471 - (cert_attr_id[0] << 24) + 472 - (cert_attr_id[1] << 16), 473 - &b); 474 - pkcs_objx->AddObjectSpec(objSpec); 475 + Buffer b = channel->CreatePKCS11CertAttrsBuffer( 476 + key_type, cert_attr_id, label, keyid); 477 + ObjectSpec objSpec = 478 + ObjectSpec::ParseFromTokenData( 479 + (cert_attr_id[0] << 24) + 480 + (cert_attr_id[1] << 16), 481 + &b); 482 + pkcs_objx->AddObjectSpec(objSpec); 483 } else { 484 - RA::Debug(LL_PER_CONNECTION,FN, 485 - "About to create PKCS#11 certificate Attributes"); 486 - rc = channel->CreatePKCS11CertAttrs(key_type, cert_attr_id, label, keyid); 487 - if (rc == -1) { 488 - RA::Error(LL_PER_CONNECTION,FN, 489 - "PKCS11 Certificate attributes creation failed"); 490 - status = STATUS_ERROR_MAC_ENROLL_PDU; 491 + RA::Debug(LL_PER_CONNECTION,FN, 492 + "About to create PKCS#11 certificate Attributes"); 493 + rc = channel->CreatePKCS11CertAttrs(key_type, cert_attr_id, label, keyid); 494 + if (rc == -1) { 495 + RA::Error(LL_PER_CONNECTION,FN, 496 + "PKCS11 Certificate attributes creation failed"); 497 + status = STATUS_ERROR_MAC_ENROLL_PDU; 498 PR_snprintf(audit_msg, 512, "PKCS11 Certificate attributes creation failed"); 499 - goto loser; 500 - } 501 + goto loser; 502 + } 503 } 504 505 if (pkcs11obj_enable) { 506 - RA::Debug(LL_PER_CONNECTION,FN, 507 - "Create PKCS11 Private Key Attributes Buffer"); 508 - Buffer b = channel->CreatePKCS11PriKeyAttrsBuffer(key_type, 509 - pri_attr_id, label, keyid, modulus, OP_PREFIX, 510 - tokenType, keyTypePrefix); 511 - ObjectSpec objSpec = 512 - ObjectSpec::ParseFromTokenData( 513 - (pri_attr_id[0] << 24) + 514 - (pri_attr_id[1] << 16), 515 - &b); 516 - pkcs_objx->AddObjectSpec(objSpec); 517 + RA::Debug(LL_PER_CONNECTION,FN, 518 + "Create PKCS11 Private Key Attributes Buffer"); 519 + 520 + Buffer b; 521 + if (!isECC) { 522 + b = channel->CreatePKCS11PriKeyAttrsBuffer(key_type, 523 + pri_attr_id, label, keyid, modulus, OP_PREFIX, 524 + tokenType, keyTypePrefix); 525 + 526 + } else { //isECC 527 + eccParams = &pk_p->u.ec.DEREncodedParams; 528 + b = channel->CreatePKCS11ECCPriKeyAttrsBuffer(key_type, 529 + pri_attr_id, label, keyid, eccParams, OP_PREFIX, 530 + tokenType, keyTypePrefix); 531 + } 532 + ObjectSpec objSpec = 533 + ObjectSpec::ParseFromTokenData( 534 + (pri_attr_id[0] << 24) + 535 + (pri_attr_id[1] << 16), 536 + &b); 537 + pkcs_objx->AddObjectSpec(objSpec); 538 } else { 539 RA::Debug(LL_PER_CONNECTION,FN, 540 "Create PKCS11 Private Key Attributes"); 541 @@ -863,27 +886,34 @@ 542 } 543 544 if (pkcs11obj_enable) { 545 - Buffer b = channel->CreatePKCS11PubKeyAttrsBuffer(key_type, 546 - pub_attr_id, label, keyid, 547 - exponent, modulus, OP_PREFIX, tokenType, keyTypePrefix); 548 - ObjectSpec objSpec = 549 - ObjectSpec::ParseFromTokenData( 550 - (pub_attr_id[0] << 24) + 551 - (pub_attr_id[1] << 16), 552 - &b); 553 - pkcs_objx->AddObjectSpec(objSpec); 554 + Buffer b; 555 + if (!isECC) { 556 + b = channel->CreatePKCS11PubKeyAttrsBuffer(key_type, 557 + pub_attr_id, label, keyid, 558 + exponent, modulus, OP_PREFIX, tokenType, keyTypePrefix); 559 + } else { 560 + b = channel->CreatePKCS11ECCPubKeyAttrsBuffer(key_type, 561 + pub_attr_id, label, keyid,&pk_p->u.ec, eccParams, 562 + OP_PREFIX, tokenType, keyTypePrefix); 563 + } 564 + ObjectSpec objSpec = 565 + ObjectSpec::ParseFromTokenData( 566 + (pub_attr_id[0] << 24) + 567 + (pub_attr_id[1] << 16), 568 + &b); 569 + pkcs_objx->AddObjectSpec(objSpec); 570 } else { 571 - RA::Debug(LL_PER_CONNECTION,FN, 572 - "Create PKCS11 Public Key Attributes"); 573 - rc = channel->CreatePKCS11PubKeyAttrs(key_type, pub_attr_id, label, keyid, 574 + RA::Debug(LL_PER_CONNECTION,FN, 575 + "Create PKCS11 Public Key Attributes"); 576 + rc = channel->CreatePKCS11PubKeyAttrs(key_type, pub_attr_id, label, keyid, 577 exponent, modulus, OP_PREFIX, tokenType, keyTypePrefix); 578 - if (rc == -1) { 579 - RA::Error(LL_PER_CONNECTION,FN, 580 - "PKCS11 public key attributes creation failed"); 581 - status = STATUS_ERROR_MAC_ENROLL_PDU; 582 + if (rc == -1) { 583 + RA::Error(LL_PER_CONNECTION,FN, 584 + "PKCS11 public key attributes creation failed"); 585 + status = STATUS_ERROR_MAC_ENROLL_PDU; 586 PR_snprintf(audit_msg, 512, "PKCS11 public key attributes creation failed"); 587 - goto loser; 588 - } 589 + goto loser; 590 + } 591 } 592 RA::Debug(LL_PER_CONNECTION,FN, "End of keygen/certificate enrollment"); 593 594 @@ -982,11 +1012,22 @@ 595 pretty_cuid = NULL; 596 } 597 if (pk_p != NULL) { 598 + // Handle ECC case 599 +/ 600 + if (isECC && (eccParams != NULL)) { 601 + RA::Debug(LL_PER_CONNECTION,FN,"DoEnrollment about to free eccParams"); 602 + SECITEM_FreeItem((SECItem ) eccParams, PR_TRUE); 603 + } 604 +/ 605 + 606 if (serverKeygen) { 607 + RA::Debug(LL_PER_CONNECTION,FN,"DoEnrollment about to call SECKEY_DestroyPublicKey on pk_p"); 608 SECKEY_DestroyPublicKey(pk_p); 609 } else { 610 + RA::Debug(LL_PER_CONNECTION,FN,"DoEnrollment about to call free on pk_p"); 611 free(pk_p); 612 } 613 + 614 pk_p = NULL; 615 } 616 return status; 617 @@ -3055,6 +3096,11 @@ 618 PR_snprintf((char )configname, 256, "%s.keySize", keyTypePrefix); 619 int keySize = RA::GetConfigStore()->GetConfigAsInt(configname, 1024); 620 621 + 622 + PR_snprintf((char )configname, 256, "%s.alg", keyTypePrefix); 623 + //Default RSA_CRT=2 624 + BYTE algorithm = (BYTE) RA::GetConfigStore()->GetConfigAsInt(configname, 2); 625 + 626 PR_snprintf((char )configname, 256, "%s.publisherId", keyTypePrefix); 627 const char publisherId = RA::GetConfigStore()->GetConfigAsString(configname, NULL); 628 629 @@ -3105,7 +3151,7 @@ 630 msn, 631 khex, (TokenKeyType)keyTypeEnum, profileId, userid, certId,publisherId, certAttrId, priKeyAttrId, 632 pubKeyAttrId, (keyUser << 4)+priKeyNumber, 633 - (keyUsage << 4)+pubKeyNumber, keySize, caconnid, keyTypePrefix,(char )final_applet_version); 634 + (keyUsage << 4)+pubKeyNumber, algorithm, keySize, caconnid, keyTypePrefix,(char )final_applet_version); 635 636 if (o_status != STATUS_NO_ERROR) { 637 r = false; 638 Index: tps/src/cms/CertEnroll.cpp 639 =================================================================== 640 --- tps/src/cms/CertEnroll.cpp (revision 2471) 641 +++ tps/src/cms/CertEnroll.cpp (working copy) 642 @@ -19,6 +19,7 @@ 643 // --- END COPYRIGHT BLOCK --- 644 645 #include 646 +#include 647 648 #include "main/RA_Session.h" 649 #include "main/RA_Msg.h" 650 @@ -35,6 +36,7 @@ 651 #include "base64.h" 652 #include "nssb64.h" 653 #include "prlock.h" 654 +#include "secoidt.h" 655 656 #include "main/Memory.h" 657 658 @@ -49,6 +51,131 @@ 659 #define TOKENDB_PUBLIC 660 #endif / !XP_WIN32 / 661 662 +//ECC curve information 663 + 664 +typedef struct curveNameTagPairStr { 665 + char curveName; 666 + SECOidTag curveOidTag; 667 +} CurveNameTagPair; 668 + 669 + 670 +static CurveNameTagPair nameTagPair[] = 671 +{ 672 + { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, 673 + { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, 674 + { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, 675 + { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, 676 + { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, 677 + { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, 678 + { "prime256v1", SEC_OID_ANSIX962_EC_PRIME256V1 }, 679 + 680 + { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, 681 + { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, 682 + { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, 683 + { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, 684 + { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, 685 + { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, 686 + { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, 687 + { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, 688 + { "secp192r1", SEC_OID_ANSIX962_EC_PRIME192V1 }, 689 + { "nistp192", SEC_OID_ANSIX962_EC_PRIME192V1 }, 690 + { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, 691 + { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, 692 + { "nistp224", SEC_OID_SECG_EC_SECP224R1}, 693 + { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, 694 + { "secp256r1", SEC_OID_ANSIX962_EC_PRIME256V1 }, 695 + { "nistp256", SEC_OID_ANSIX962_EC_PRIME256V1 }, 696 + { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, 697 + { "nistp384", SEC_OID_SECG_EC_SECP384R1}, 698 + { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, 699 + { "nistp521", SEC_OID_SECG_EC_SECP521R1}, 700 + 701 + { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, 702 + { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, 703 + { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, 704 + { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, 705 + { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, 706 + { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, 707 + { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, 708 + { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, 709 + { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, 710 + { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, 711 + { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, 712 + { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, 713 + { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, 714 + { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, 715 + { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, 716 + { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, 717 + { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, 718 + { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, 719 + { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, 720 + { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, 721 + 722 + { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, 723 + { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, 724 + { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, 725 + { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, 726 + { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, 727 + { "nistk163", SEC_OID_SECG_EC_SECT163K1}, 728 + { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, 729 + { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, 730 + { "nistb163", SEC_OID_SECG_EC_SECT163R2}, 731 + { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, 732 + { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, 733 + { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, 734 + { "nistk233", SEC_OID_SECG_EC_SECT233K1}, 735 + { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, 736 + { "nistb233", SEC_OID_SECG_EC_SECT233R1}, 737 + { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, 738 + { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, 739 + { "nistk283", SEC_OID_SECG_EC_SECT283K1}, 740 + { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, 741 + { "nistb283", SEC_OID_SECG_EC_SECT283R1}, 742 + { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, 743 + { "nistk409", SEC_OID_SECG_EC_SECT409K1}, 744 + { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, 745 + { "nistb409", SEC_OID_SECG_EC_SECT409R1}, 746 + { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, 747 + { "nistk571", SEC_OID_SECG_EC_SECT571K1}, 748 + { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, 749 + { "nistb571", SEC_OID_SECG_EC_SECT571R1}, 750 + 751 +}; 752 + 753 +SECKEYECParams * 754 +CertEnroll::encode_ec_params(char curve) 755 +{ 756 + SECKEYECParams ecparams; 757 + SECOidData oidData = NULL; 758 + SECOidTag curveOidTag = SEC_OID_UNKNOWN; / default / 759 + int i, numCurves; 760 + 761 + if (curve && curve) { 762 + numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); 763 + for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); 764 + i++) { 765 + if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) 766 + curveOidTag = nameTagPair[i].curveOidTag; 767 + } 768 + } 769 + 770 + if ((curveOidTag == SEC_OID_UNKNOWN) || 771 + (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { 772 + return NULL; 773 + } 774 + 775 + ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); 776 + 777 + if (!ecparams) 778 + return NULL; 779 + 780 + ecparams->data[0] = SEC_ASN1_OBJECT_ID; 781 + ecparams->data[1] = oidData->oid.len; 782 + memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); 783 + 784 + return ecparams; 785 +} 786 + 787 /* 788 * Constructs handle for Certificate Enrollment 789 / 790 @@ -328,8 +455,20 @@ 791 * Short Exponent Length 792 * 793 * Byte[] Exponent 794 + * 795 + * 796 + * ECC KeyBlob Format (ECC Public Key) 797 + * ---------------------------------- 798 + * 799 + * Byte Encoding (0 for plaintext) 800 * 801 - * 802 + * Byte Key Type (10 for ECC public) 803 + * 804 + * Short Key Length (256, 384, 521 high byte first) 805 + * 806 + * Byte[] Key (W) 807 + * 808 + * 809 * Signature Format (Proof) 810 * --------------------------------------- 811 * 812 @@ -369,7 +508,7 @@ 813 / 814 815 SECKEYPublicKey CertEnroll::ParsePublicKeyBlob(unsigned char blob, 816 - Buffer challenge) 817 + Buffer challenge, bool isECC) 818 { 819 char configname[5000]; 820 SECKEYPublicKey pk = NULL; 821 @@ -404,7 +543,7 @@ 822 pkeyb_len = (unsigned short) ((len0 << 8) | (len1 & 0xFF)); 823 824 RA::Debug(LL_PER_PDU, "CertEnroll::ParsePublicKeyBlob", 825 - "pkeyb_len =%d",pkeyb_len); 826 + "pkeyb_len =%d isECC: %d",pkeyb_len, isECC); 827 828 if (pkeyb_len <= 0) { 829 RA::Error("CertEnroll::ParsePublicKeyBlob", "public key blob length = %d", pkeyb_len); 830 @@ -431,51 +570,112 @@ 831 832 // convert pkeyb to pkey 833 // 1 byte encoding, 1 byte key type, 2 bytes key length, then the key 834 + 835 + // for ECC 836 + unsigned short ecc_pkey_len = 0; 837 + // ecc key blob 838 + unsigned char eccpb = NULL; 839 + 840 + // for RSA 841 + unsigned short mod_len = 0; 842 + unsigned short exp_len = 0; 843 + // public key mod blob 844 + unsigned char * modb = NULL; 845 + // public key exp blob 846 + unsigned char * expb = NULL; 847 + 848 unsigned short pkey_offset = 4; 849 - // now, convert lengths for modulus and exponent 850 len0 = pkeyb[pkey_offset]; 851 len1 = pkeyb[pkey_offset + 1]; 852 - unsigned short mod_len = (len0 << 8 | len1); 853 854 - len0 = pkeyb[pkey_offset + 2 + mod_len]; 855 - len1 = pkeyb[pkey_offset + 2 + mod_len + 1]; 856 - unsigned short exp_len = (len0 << 8 | len1); 857 + if (!isECC) { 858 + // now, convert lengths for modulus and exponent 859 + mod_len = (len0 << 8 | len1); 860 861 + len0 = pkeyb[pkey_offset + 2 + mod_len]; 862 + len1 = pkeyb[pkey_offset + 2 + mod_len + 1]; 863 + exp_len = (len0 << 8 | len1); 864 865 - // public key mod blob 866 - unsigned char * modb = &pkeyb[pkey_offset + 2]; 867 + modb = &pkeyb[pkey_offset + 2]; 868 + expb = &pkeyb[pkey_offset + 2 + mod_len + 2]; 869 870 - // public key exp blob 871 - unsigned char * expb = &pkeyb[pkey_offset + 2 + mod_len + 2]; 872 + } else { 873 + ecc_pkey_len = (len0 << 8 | len1); 874 + eccpb = &pkeyb[pkey_offset + 2]; 875 + } 876 877 // construct SECItem 878 + 879 + // for RSA 880 SECItem siMod; 881 - siMod.type = (SECItemType) 0; 882 - siMod.data = (unsigned char ) modb; 883 - siMod.len = mod_len; 884 - 885 SECItem siExp; 886 - siExp.type = (SECItemType) 0; 887 - siExp.data = (unsigned char )expb; 888 - siExp.len = exp_len; 889 - 890 - // construct SECKEYRSAPublicKeyStr 891 SECKEYRSAPublicKeyStr rsa_pks; 892 - rsa_pks.modulus = siMod; 893 - rsa_pks.publicExponent = siExp; 894 895 - // construct SECKEYPublicKey 896 - // this is to be returned 897 + // for ECC 898 + SECItem eccValue; 899 + SECKEYECPublicKeyStr ecc_pks; 900 + SECKEYECParams ecc_key_params = NULL; 901 + 902 pk = (SECKEYPublicKey ) malloc(sizeof(SECKEYPublicKey)); 903 - pk->keyType = rsaKey; 904 - pk->pkcs11Slot = NULL; 905 - pk->pkcs11ID = CK_INVALID_HANDLE; 906 - pk->u.rsa = rsa_pks; 907 908 + assert(pk); 909 + 910 + if (!isECC) { 911 + 912 + siMod.type = (SECItemType) 0; 913 + siMod.data = (unsigned char ) modb; 914 + siMod.len = mod_len; 915 + 916 + siExp.type = (SECItemType) 0; 917 + siExp.data = (unsigned char )expb; 918 + siExp.len = exp_len; 919 + 920 + // construct SECKEYRSAPublicKeyStr 921 + rsa_pks.modulus = siMod; 922 + rsa_pks.publicExponent = siExp; 923 + 924 + pk->keyType = rsaKey; 925 + pk->pkcs11Slot = NULL; 926 + pk->pkcs11ID = CK_INVALID_HANDLE; 927 + pk->u.rsa = rsa_pks; 928 + } else { 929 + // ECC 930 + len0 = blob[pkeyb_len_offset +4]; 931 + len1 = blob[pkeyb_len_offset +5]; 932 + int keyCurveSize = (len0 << 8 | len1); 933 + 934 + RA::Debug(LL_PER_PDU, "CertEnroll::ParsePublicKeyBlob", 935 + "keyCurveSize =%d",keyCurveSize); 936 + 937 + char curve[56] = ""; 938 + snprintf(curve, 56, "nistp%d",keyCurveSize ); 939 + 940 + ecc_key_params = encode_ec_params(curve); 941 + 942 + if (ecc_key_params == NULL) { 943 + free(pk); 944 + pk = NULL; 945 + return NULL; 946 + } 947 + 948 + eccValue.type = (SECItemType) 0; 949 + eccValue.data = (unsigned char ) eccpb; 950 + eccValue.len = ecc_pkey_len; 951 + 952 + ecc_pks.size = keyCurveSize; 953 + ecc_pks.publicValue = eccValue; 954 + ecc_pks.DEREncodedParams = ecc_key_params; 955 + 956 + pk->keyType = ecKey; 957 + pk->pkcs11Slot = NULL; 958 + pk->pkcs11ID = CK_INVALID_HANDLE; 959 + pk->u.ec = ecc_pks; 960 + } 961 + 962 PR_snprintf((char )configname, 256, "general.verifyProof"); 963 int verifyProofEnable = RA::GetConfigStore()->GetConfigAsInt(configname, 0x1); 964 if (verifyProofEnable) { 965 - rs = verifyProof(pk, &siProof, pkeyb_len, pkeyb, challenge); 966 + rs = verifyProof(pk, &siProof, pkeyb_len, pkeyb, challenge, isECC); 967 if (rs.status == PR_FAILURE) { 968 RA::Error("CertEnroll::ParsePublicKeyBlob", 969 "verify proof failed"); 970 @@ -487,7 +687,33 @@ 971 return pk; 972 } 973 974 +/ 975 + * for debugging tokens 976 + * -- list out all tokens and thier login status 977 + / 978 +static SECStatus 979 +ListModules(void) 980 +{ 981 + PK11SlotList list; 982 + PK11SlotListElement le; 983 984 + / get them all! / 985 + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,NULL); 986 + if (list == NULL) return SECFailure; 987 + 988 + / look at each slot/ 989 + for (le = list->head ; le; le = le->next) { 990 + RA::Debug( LL_PER_PDU, "CertEnroll::ListModules", 991 + " slot: %s\n, loggedIn? %d, token: %s\n", PK11_GetSlotName(le->slot), 992 + (PK11_IsLoggedIn(le->slot, NULL) == PR_TRUE)? 1:0, 993 + PK11_GetTokenName(le->slot)); 994 + } 995 + PK11_FreeSlotList(list); 996 + 997 + return SECSuccess; 998 +} 999 + 1000 + 1001 / 1002 * verify the proof. 1003 * @param pk the public key from the input blob 1004 @@ -502,18 +728,24 @@ 1005 / 1006 ReturnStatus CertEnroll::verifyProof(SECKEYPublicKey pk, SECItem siProof, 1007 unsigned short pkeyb_len, unsigned char pkeyb, 1008 - Buffer challenge) { 1009 + Buffer challenge, bool isECC) { 1010 1011 ReturnStatus rs; 1012 VFYContext * vc = NULL; 1013 rs.statusNum = ::VRFY_SUCCESS; 1014 rs.status = PR_SUCCESS; 1015 1016 + // ListModules(); 1017 + 1018 // verify proof (signature) 1019 RA::Debug(LL_PER_PDU, "CertEnroll::verifyProof", 1020 "verify proof begins"); 1021 1022 - vc = VFY_CreateContext(pk, siProof, SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE, NULL); 1023 + if(isECC) { 1024 + vc = VFY_CreateContext(pk, siProof, SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE , NULL); 1025 + } else { 1026 + vc = VFY_CreateContext(pk, siProof, SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE, NULL); 1027 + } 1028 1029 if (vc == NULL) { 1030 RA::Error("CertEnroll::verifyProof", 1031 @@ -530,14 +762,15 @@ 1032 int i =0; 1033 for (i = 0; i<pkeyb_len; i++) { 1034 proof[i] = pkeyb[i]; 1035 + RA::Debug(LL_PER_PDU,"CertEnroll::VerifyProof", "proof[%d]=%x", i, proof[i]); 1036 } 1037 - // RA::DebugBuffer("CertEnroll::VerifyProof","VerifyProof:: challenge =", challenge); 1038 + RA::DebugBuffer("CertEnroll::VerifyProof","VerifyProof:: challenge =", challenge); 1039 unsigned char chal = (unsigned char )(BYTE ) (challenge); 1040 unsigned int j = 0; 1041 for (j=0; j < challenge->size(); i++, j++) { 1042 proof[i] = chal[j]; 1043 - // RA::Debug(LL_PER_PDU, "CertEnroll::VerifyProof","proof[%d]= %x", 1044 - // i, proof[i]); 1045 + RA::Debug(LL_PER_PDU, "CertEnroll::VerifyProof","proof[%d]= %x", 1046 + i, proof[i]); 1047 } 1048 1049 SECStatus vs = VFY_Begin(vc); 1050 @@ -547,7 +780,7 @@ 1051 vs = VFY_End(vc); 1052 if (vs == SECFailure) { 1053 RA::Error("CertEnroll::verifyProof", 1054 - "VFY_End() failed pkeyb_len=%d challenge_size=%d", pkeyb_len, challenge->size()); 1055 + "VFY_End() failed pkeyb_len=%d challenge_size=%d error=%d", pkeyb_len, challenge->size(),PR_GetError()); 1056 rs.statusNum = ::VFY_UPDATE_FAILURE; 1057 rs.status = PR_FAILURE; 1058 } 1059 Index: tps/src/include/processor/RA_Enroll_Processor.h 1060 =================================================================== 1061 --- tps/src/include/processor/RA_Enroll_Processor.h (revision 2471) 1062 +++ tps/src/include/processor/RA_Enroll_Processor.h (working copy) 1063 @@ -50,40 +50,40 @@ 1064 1065 class RA_Enroll_Processor : public RA_Processor 1066 { 1067 - public: 1068 - TPS_PUBLIC RA_Enroll_Processor(); 1069 - TPS_PUBLIC ~RA_Enroll_Processor(); 1070 - public: 1071 - int ParsePublicKeyBlob(unsigned char blob, 1072 - unsigned char challenge, 1073 - SECKEYPublicKey pk); 1074 - RA_Status DoEnrollment(AuthParams login, RA_Session session, 1075 - CERTCertificate certificates, 1076 - char origins, 1077 - char ktypes, 1078 - int pkcs11obj, 1079 - PKCS11Obj * pkcs_objx, 1080 - NameValueSet extensions, 1081 - int index, int keyTypeNum, 1082 - int start_progress, 1083 - int end_progress, 1084 - Secure_Channel channel, Buffer wrapped_challenge, 1085 - const char tokenType, 1086 - const char keyType, 1087 - Buffer key_check, 1088 - Buffer plaintext_challenge, 1089 - const char cuid, 1090 - const char msn, 1091 - const char khex, 1092 - TokenKeyType key_type, 1093 - const char profileId, 1094 - const char userid, 1095 - const char cert_id, 1096 - const char publisher_id, 1097 - const char cert_attr_id, 1098 - const char pri_attr_id, 1099 - const char pub_attr_id, 1100 - BYTE se_p1, BYTE se_p2, int keysize, const char connid, const char keyTypePrefix,char * applet_version); 1101 + public: 1102 + TPS_PUBLIC RA_Enroll_Processor(); 1103 + TPS_PUBLIC ~RA_Enroll_Processor(); 1104 + public: 1105 + int ParsePublicKeyBlob(unsigned char blob, 1106 + unsigned char challenge, 1107 + SECKEYPublicKey pk); 1108 + RA_Status DoEnrollment(AuthParams login, RA_Session session, 1109 + CERTCertificate certificates, 1110 + char origins, 1111 + char ktypes, 1112 + int pkcs11obj, 1113 + PKCS11Obj * pkcs_objx, 1114 + NameValueSet extensions, 1115 + int index, int keyTypeNum, 1116 + int start_progress, 1117 + int end_progress, 1118 + Secure_Channel channel, Buffer wrapped_challenge, 1119 + const char tokenType, 1120 + const char keyType, 1121 + Buffer key_check, 1122 + Buffer plaintext_challenge, 1123 + const char cuid, 1124 + const char msn, 1125 + const char khex, 1126 + TokenKeyType key_type, 1127 + const char profileId, 1128 + const char userid, 1129 + const char cert_id, 1130 + const char publisher_id, 1131 + const char cert_attr_id, 1132 + const char pri_attr_id, 1133 + const char pub_attr_id, 1134 + BYTE se_p1, BYTE se_p2, BYTE algorithm, int keysize, const char connid, const char keyTypePrefix,char * applet_version); 1135 1136 bool DoRenewal(const char connid, 1137 const char profileId, 1138 Index: tps/src/include/cms/CertEnroll.h 1139 =================================================================== 1140 --- tps/src/include/cms/CertEnroll.h (revision 2471) 1141 +++ tps/src/include/cms/CertEnroll.h (working copy) 1142 @@ -55,8 +55,9 @@ 1143 TOKENDB_PUBLIC CertEnroll(); 1144 TOKENDB_PUBLIC ~CertEnroll(); 1145 1146 + 1147 SECKEYPublicKey ParsePublicKeyBlob(unsigned char * /blob/, 1148 - Buffer * /challenge/); 1149 + Buffer * /challenge/, bool isECC); 1150 Buffer EnrollCertificate(SECKEYPublicKey * /pk_parsed/, 1151 const char profileId, 1152 const char * /uid/, 1153 @@ -64,12 +65,15 @@ 1154 char error_msg, 1155 SECItem encodedPublicKeyInfo = NULL); 1156 ReturnStatus verifyProof(SECKEYPublicKey /pk/, SECItem /siProof/, 1157 - unsigned short /pkeyb_len/, unsigned char /pkeyb/, 1158 - Buffer /challenge/); 1159 + unsigned short /pkeyb_len/, unsigned char /pkeyb/, 1160 + Buffer /challenge/, bool /isECC/); 1161 TOKENDB_PUBLIC Buffer RenewCertificate(PRUint64 serialno, const char connid, const char profileId, char error_msg); 1162 TOKENDB_PUBLIC int RevokeCertificate(const char reason, const char serialno, const char connid, char &status); 1163 TOKENDB_PUBLIC int UnrevokeCertificate(const char serialno, const char connid, char &status); 1164 PSHttpResponse * sendReqToCA(const char servlet, const char parameters, const char connid); 1165 Buffer * parseResponse(PSHttpResponse * /resp/); 1166 + 1167 + SECKEYECParams * encode_ec_params(char curve); 1168 + 1169 }; 1170 #endif / CERTENROLL_H / 1171 Index: tps/src/include/main/Buffer.h 1172 =================================================================== 1173 --- tps/src/include/main/Buffer.h (revision 2471) 1174 +++ tps/src/include/main/Buffer.h (working copy) 1175 @@ -167,6 +167,9 @@ 1176 / 1177 TPS_PUBLIC void replace(unsigned int i, const BYTE cpy, unsigned int n); 1178 1179 + TPS_PUBLIC unsigned char getBuf(); 1180 + TPS_PUBLIC unsigned int getLen(); 1181 + 1182 / 1183 * returns a hex version of the buffer 1184 / 1185 Index: tps/src/include/engine/RA.h 1186 =================================================================== 1187 --- tps/src/include/engine/RA.h (revision 2471) 1188 +++ tps/src/include/engine/RA.h (working copy) 1189 @@ -79,6 +79,13 @@ 1190 LL_ALL_DATA_IN_PDU = 9 1191 }; 1192 1193 +enum RA_Algs { 1194 + ALG_RSA = 1, 1195 + ALG_RSA_CRT = 2, 1196 + ALG_DSA = 3, 1197 + ALG_EC_F2M = 4, 1198 + ALG_EC_FP = 5 1199 +}; 1200 1201 #ifdef XP_WIN32 1202 #define TPS_PUBLIC __declspec(dllexport) 1203 @@ -124,12 +131,12 @@ 1204 char kek_kekSessionKey_s, 1205 char keycheck_s, 1206 const char connId); 1207 - static void ServerSideKeyGen(RA_Session session, const char cuid, 1208 + static void ServerSideKeyGen(RA_Session session, const char cuid, 1209 const char userid, char kekSessionKey_s, 1210 - char publickey_s, 1211 + char publickey_s, 1212 char wrappedPrivateKey_s, 1213 char ivParam_s, const char connId, 1214 - bool archive, int keysize); 1215 + bool archive, int keysize, bool isECC); 1216 static void RecoverKey(RA_Session session, const char cuid, 1217 const char userid, char kekSessionKey_s, 1218 char cert_s, char publickey_s, 1219 @@ -363,6 +370,7 @@ 1220 static void CleanupPublishers(); 1221 static int Failover(HttpConnection &conn, int len); 1222 1223 + static bool isAlgorithmECC(BYTE algorithm); 1224 TPS_PUBLIC static SECCertificateUsage getCertificateUsage(const char certusage); 1225 TPS_PUBLIC static bool verifySystemCertByNickname(const char nickname, const char certUsage); 1226 TPS_PUBLIC static bool verifySystemCerts(); 1227 Index: tps/src/include/channel/Secure_Channel.h 1228 =================================================================== 1229 --- tps/src/include/channel/Secure_Channel.h (revision 2471) 1230 +++ tps/src/include/channel/Secure_Channel.h (working copy) 1231 @@ -125,10 +125,18 @@ 1232 int CreatePKCS11CertAttrs(TokenKeyType type, const char id, const char label, Buffer keyid); 1233 Buffer CreatePKCS11PriKeyAttrsBuffer(TokenKeyType type, const char id, const char label, Buffer keyid, 1234 Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix); 1235 + 1236 + Buffer CreatePKCS11ECCPriKeyAttrsBuffer(TokenKeyType type, const char id, const char label, Buffer keyid, 1237 + SECKEYECParams ecParams, const char opType, const char tokenType, const char keyTypePrefix); 1238 + 1239 int CreatePKCS11PriKeyAttrs(TokenKeyType type, const char id, const char label, Buffer keyid, 1240 Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix); 1241 Buffer CreatePKCS11PubKeyAttrsBuffer(TokenKeyType type, const char id, const char label, Buffer keyid, 1242 Buffer exponent, Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix); 1243 + 1244 + Buffer CreatePKCS11ECCPubKeyAttrsBuffer(TokenKeyType key_type, const char id, const char label, Buffer keyid, SECKEYECPublicKey publicKey, 1245 + SECKEYECParams ecParams, const char opType, const char tokenType, const char keyTypePrefix); 1246 + 1247 int CreatePKCS11PubKeyAttrs(TokenKeyType type, const char id, const char label, Buffer keyid, 1248 Buffer exponent, Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix); 1249 APDU_Response SendTokenAPU(APDU apdu); 1250 Index: tps/src/main/Buffer.cpp 1251 =================================================================== 1252 --- tps/src/main/Buffer.cpp (revision 2471) 1253 +++ tps/src/main/Buffer.cpp (working copy) 1254 @@ -222,6 +222,16 @@ 1255 return s; 1256 } 1257 1258 +TPS_PUBLIC unsigned char 1259 +Buffer::getBuf() { 1260 + return (unsigned char ) buf; 1261 +} 1262 + 1263 +TPS_PUBLIC unsigned int 1264 +Buffer::getLen() { 1265 + return len; 1266 +} 1267 + 1268 TPS_PUBLIC char * 1269 Buffer::toHex() 1270 { 1271 Index: tps/src/main/ObjectSpec.cpp 1272 =================================================================== 1273 --- tps/src/main/ObjectSpec.cpp (revision 2471) 1274 +++ tps/src/main/ObjectSpec.cpp (working copy) 1275 @@ -190,6 +190,7 @@ 1276 case CKA_KEY_TYPE: 1277 type = DATATYPE_INTEGER; 1278 data = b->substr(curpos+6, 4); 1279 + found = 1; 1280 / build by PKCS11 / 1281 break; 1282 case CKA_CLASS: 1283 @@ -208,6 +209,18 @@ 1284 data = b->substr(curpos+6, 4); 1285 / build by PKCS11 / 1286 break; 1287 + 1288 + case CKA_EC_PARAMS: 1289 + type = DATATYPE_STRING; 1290 + data = b->substr(curpos+6, attribute_size); 1291 + found = 1; 1292 + break; 1293 + 1294 + case CKA_EC_POINT: 1295 + type = DATATYPE_STRING; 1296 + data = b->substr(curpos+6, attribute_size); 1297 + found = 1; 1298 + break; 1299 default: 1300 RA::Debug("ObjectSpec::ParseKeyBlob", 1301 "skipped attribute_id = %lx", 1302 Index: tps/src/engine/RA.cpp 1303 =================================================================== 1304 --- tps/src/engine/RA.cpp (revision 2471) 1305 +++ tps/src/engine/RA.cpp (working copy) 1306 @@ -1287,7 +1287,7 @@ 1307 char publicKey_s, 1308 char wrappedPrivateKey_s, 1309 char ivParam_s, const char connId, 1310 - bool archive, int keysize) 1311 + bool archive, int keysize, bool isECC) 1312 { 1313 1314 const char FN="RA::ServerSideKeyGen"; 1315 @@ -1357,8 +1357,26 @@ 1316 RA::Debug(LL_PER_CONNECTION, FN, 1317 "wrappedDESKey_s=%s", wrappedDESKey_s); 1318 1319 - PR_snprintf((char )body, MAX_BODY_LEN, 1320 - "archive=%s&CUID=%s&userid=%s&keysize=%d&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, keysize, wrappedDESKey_s); 1321 + if (isECC) { 1322 + char eckeycurve = NULL; 1323 + if (keysize == 521) { 1324 + eckeycurve = "nistp521"; 1325 + } else if (keysize == 384) { 1326 + eckeycurve = "nistp384"; 1327 + } else if (keysize == 256) { 1328 + eckeycurve = "nistp256"; 1329 + } else { 1330 + RA::Debug(LL_PER_CONNECTION, FN, 1331 + "unrecognized ECC keysize %d, setting to 256", keysize); 1332 + keysize = 256; 1333 + eckeycurve = "nistp256"; 1334 + } 1335 + PR_snprintf((char )body, MAX_BODY_LEN, 1336 + "archive=%s&CUID=%s&userid=%s&keytype=EC&eckeycurve=%s&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, eckeycurve, wrappedDESKey_s); 1337 + } else { 1338 + PR_snprintf((char )body, MAX_BODY_LEN, 1339 + "archive=%s&CUID=%s&userid=%s&keysize=%d&keytype=RSA&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, keysize, wrappedDESKey_s); 1340 + } 1341 RA::Debug(LL_PER_CONNECTION, FN, 1342 "sending to DRM: query=%s", body); 1343 1344 @@ -3612,3 +3630,15 @@ 1345 return newKey; 1346 } 1347 1348 +bool RA::isAlgorithmECC(BYTE alg) 1349 +{ 1350 + bool result = false; 1351 + 1352 + if (alg == ALG_EC_F2M || alg == ALG_EC_FP) 1353 + result = true; 1354 + 1355 + RA::Debug(LL_PER_SERVER, "RA::isAlgorithmECC", " alg: %d result: %d", alg, result); 1356 + 1357 + return result; 1358 +} 1359 + 1360 Index: tps/src/channel/Secure_Channel.cpp 1361 =================================================================== 1362 --- tps/src/channel/Secure_Channel.cpp (revision 2471) 1363 +++ tps/src/channel/Secure_Channel.cpp (working copy) 1364 @@ -38,6 +38,7 @@ 1365 #include "apdu/Read_Object_APDU.h" 1366 #include "apdu/Write_Object_APDU.h" 1367 #include "apdu/Generate_Key_APDU.h" 1368 +#include "apdu/Generate_Key_ECC_APDU.h" 1369 #include "apdu/Put_Key_APDU.h" 1370 #include "apdu/Delete_File_APDU.h" 1371 #include "apdu/Load_File_APDU.h" 1372 @@ -142,6 +143,7 @@ 1373 } 1374 } 1375 1376 + RA::Debug(LL_PER_PDU,"Secure_Channel::ComputeAPDU","Completed apdu."); 1377 rc = 1; 1378 loser: 1379 if( mac != NULL ) { 1380 @@ -171,8 +173,8 @@ 1381 apdu->GetDataToMAC(data); 1382 1383 // developer debugging only - not for deployment 1384 - // RA::DebugBuffer("Secure_Channel::ComputeAPDUMac", "Data To MAC'ed", 1385 - // &data); 1386 + RA::DebugBuffer("Secure_Channel::ComputeAPDUMac", "Data To MAC'ed", 1387 + &data); 1388 1389 // Compute MAC will padd the data if it is 1390 // not in 8 byte multiples 1391 @@ -180,6 +182,8 @@ 1392 apdu->SetMAC(mac); 1393 m_icv = mac; 1394 1395 + RA::DebugBuffer("Secure_Channel::ComputeAPDUMac ", "mac", 1396 + mac); 1397 return mac; 1398 } / EncodeAPDUMac / 1399 1400 @@ -1340,6 +1344,8 @@ 1401 { 1402 int rc = -1; 1403 Generate_Key_APDU generate_key_apdu = NULL; 1404 + Generate_Key_ECC_APDU generate_key_ecc_apdu = NULL; 1405 + 1406 APDU_Response response = NULL; 1407 RA_Token_PDU_Request_Msg token_pdu_request_msg = NULL; 1408 RA_Token_PDU_Response_Msg token_pdu_response_msg = NULL; 1409 @@ -1348,9 +1354,19 @@ 1410 1411 RA::Debug("Secure_Channel::GenerateKey", 1412 "Secure_Channel::GenerateKey"); 1413 - generate_key_apdu = new Generate_Key_APDU(p1, p2, alg, keysize, option, 1414 - alg, wrapped_challenge, key_check); 1415 - rc = ComputeAPDU(generate_key_apdu); 1416 + 1417 + bool isECC = RA::isAlgorithmECC(alg); 1418 + 1419 + if (isECC) { 1420 + generate_key_ecc_apdu = new Generate_Key_ECC_APDU(p1, p2, alg, keysize, option, 1421 + alg, wrapped_challenge, key_check); 1422 + rc = ComputeAPDU(generate_key_ecc_apdu); 1423 + } else { 1424 + generate_key_apdu = new Generate_Key_APDU(p1, p2, alg, keysize, option, 1425 + alg, wrapped_challenge, key_check); 1426 + rc = ComputeAPDU(generate_key_apdu); 1427 + } 1428 + 1429 if (rc == -1) 1430 goto loser; 1431 1432 @@ -1358,8 +1374,15 @@ 1433 mac = ComputeAPDUMac(generate_key_apdu); 1434 generate_key_apdu->SetMAC(mac); 1435 / 1436 - token_pdu_request_msg = new RA_Token_PDU_Request_Msg( 1437 - generate_key_apdu); 1438 + 1439 + if (generate_key_ecc_apdu != NULL ) { 1440 + token_pdu_request_msg = new RA_Token_PDU_Request_Msg( 1441 + generate_key_ecc_apdu); 1442 + } else { 1443 + token_pdu_request_msg = new RA_Token_PDU_Request_Msg( 1444 + generate_key_apdu); 1445 + } 1446 + 1447 m_session->WriteMsg(token_pdu_request_msg); 1448 RA::Debug("Secure_Channel::GenerateKey", 1449 "Sent token_pdu_request_msg"); 1450 @@ -2177,9 +2200,9 @@ 1451 Buffer b(256); // allocate some space 1452 b.resize(7); // this keeps the allocated space around 1453 1454 - RA::Debug("Secure_Channel::CreatePKCS11CertAttrs", "id=%s", id); 1455 - RA::Debug("Secure_Channel::CreatePKCS11CertAttrs", "label=%s", label); 1456 - RA::DebugBuffer("Secure_Channel::CreatePKCS11CertAttrs", "keyid", keyid); 1457 + RA::Debug("Secure_Channel::CreatePKCS11CertAttrsBuffer", "id=%s", id); 1458 + RA::Debug("Secure_Channel::CreatePKCS11CertAttrsBuffer", "label=%s", label); 1459 + RA::DebugBuffer("Secure_Channel::CreatePKCS11CertAttrsBuffer", "keyid", keyid); 1460 AppendAttribute(b, CKA_LABEL, strlen(label), (BYTE)label); 1461 // hash of pubk 1462 AppendAttribute(b, CKA_ID, keyid->size(), (BYTE)keyid); 1463 @@ -2301,6 +2324,7 @@ 1464 M 00020001010000000100010100000100 1465 M 00040000000000000000000403000000 1466 / 1467 + 1468 Buffer Secure_Channel::CreatePKCS11PriKeyAttrsBuffer(TokenKeyType key_type, const char id, const char label, Buffer keyid, 1469 Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix) 1470 { 1471 @@ -2383,6 +2407,39 @@ 1472 1473 } / CreatePKCS11PriKeyAttrs / 1474 1475 +Buffer Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer(TokenKeyType type, const char id, const char label, Buffer keyid, 1476 + SECKEYECParams ecParams, const char opType, const char tokenType, const char keyTypePrefix) 1477 +{ 1478 + 1479 + BYTE keytype[8] = { 3,0,0,0 }; 1480 + BYTE p11class[4] = { 3,0,0,0 }; 1481 + 1482 + Buffer b(256); // allocate some space 1483 + b.resize(7); // this keeps the allocated space around 1484 + 1485 + if (label != NULL) 1486 + RA::Debug("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "label=%s", label); 1487 + if (keyid != NULL) 1488 + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "keyid", keyid); 1489 + if (id != NULL) 1490 + RA::Debug("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "id=%s",id); 1491 + 1492 + AppendAttribute(b,CKA_KEY_TYPE, 4, keytype); 1493 + AppendAttribute(b,CKA_CLASS, 4, p11class ); 1494 + // hash of pubk 1495 + AppendAttribute(b,CKA_ID, keyid->size(), (BYTE)keyid); 1496 + 1497 + AppendAttribute(b,CKA_EC_PARAMS, ecParams->len, ecParams->data); 1498 + AppendKeyCapabilities(b, opType, tokenType, keyTypePrefix, "private"); 1499 + 1500 + FinalizeBuffer(b, id); 1501 + 1502 + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "buffer", &b); 1503 + 1504 + return b; 1505 + 1506 +} 1507 + 1508 / 1509 Public Key: (k1) 1510 CKA_PUBLIC_EXPONENT(0x0122) 1511 @@ -2461,6 +2518,43 @@ 1512 return b; 1513 } / CreatePKCS11PubKeyAttrs / 1514 1515 + 1516 +Buffer Secure_Channel::CreatePKCS11ECCPubKeyAttrsBuffer(TokenKeyType key_type, const char id, const char label, Buffer keyid, 1517 + SECKEYECPublicKey publicKey, SECKEYECParams ecParams, const char opType, const char tokenType, const char keyTypePrefix) 1518 +{ 1519 + BYTE p11class[4] = { 2,0,0,0 }; 1520 + // BYTE ZERO[1] = { 0 }; 1521 + // BYTE ONE[1] = { 1 }; 1522 + // char configname[256]; 1523 + 1524 + BYTE keytype[4] = { 3,0,0,0 }; 1525 + Buffer b(256); // allocate some space 1526 + b.resize(7); // this keeps the allocated space around 1527 + 1528 + RA::Debug("Secure_Channel::CreatePKCS11ECCPubAttrsBuffer", "label=%s", label); 1529 + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPubAttrsBuffer", "keyid", keyid); 1530 + 1531 + // XXX TUES 1532 + // hash of pubk 1533 + AppendAttribute(b,CKA_ID, keyid->size(), (BYTE)keyid); 1534 + AppendAttribute(b, CKA_CLASS, 4, p11class ); // type of object 1535 + AppendAttribute(b,CKA_KEY_TYPE, 4, keytype); // CKK_EC key type 1536 + AppendAttribute(b,CKA_EC_PARAMS, ecParams->len, (BYTE ) ecParams->data); 1537 + AppendAttribute(b, CKA_EC_POINT, publicKey->publicValue.len, (BYTE ) publicKey->publicValue.data); 1538 + 1539 + AppendKeyCapabilities(b, opType, tokenType, keyTypePrefix, "public"); 1540 + 1541 + 1542 + FinalizeBuffer(b, id); 1543 + 1544 + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPubAttrsBuffer", "buffer", &b); 1545 + 1546 + return b; 1547 +} / CreatePKCS11ECCPubKeyAttrs / 1548 + 1549 + 1550 + 1551 + 1552 int Secure_Channel::CreatePKCS11PubKeyAttrs(TokenKeyType key_type, const char id, const char label, Buffer keyid, 1553 Buffer exponent, Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix) 1554 { 1555 Index: kra/src/com/netscape/kra/NetkeyKeygenService.java 1556 =================================================================== 1557 --- kra/src/com/netscape/kra/NetkeyKeygenService.java (revision 2471) 1558 +++ kra/src/com/netscape/kra/NetkeyKeygenService.java (working copy) 1559 @@ -62,7 +62,10 @@ 1560 import com.netscape.certsrv.authentication.; 1561 import com.netscape.certsrv.apps.; 1562 import com.netscape.certsrv.apps.CMS; 1563 +import com.netscape.cmsutil.crypto.CryptoUtil; 1564 +import com.netscape.cms.servlet.key.KeyRecordParser; 1565 1566 + 1567 //for b64 encoding 1568 import org.mozilla.jss.util.Base64OutputStream; 1569 import java.io.ByteArrayOutputStream; 1570 @@ -146,7 +149,7 @@ 1571 } 1572 1573 public KeyPair generateKeyPair( 1574 - KeyPairAlgorithm kpAlg, int keySize, PQGParams pqg) 1575 + KeyPairAlgorithm kpAlg, int keySize, String keyCurve, PQGParams pqg) 1576 throws NoSuchAlgorithmException, TokenException, InvalidAlgorithmParameterException, 1577 InvalidParameterException, PQGParamGenException { 1578 1579 @@ -165,20 +168,29 @@ 1580 sensitive == true 1581 extractable == true 1582 / 1583 + 1584 KeyPairGenerator kpGen = token.getKeyPairGenerator(kpAlg); 1585 IConfigStore config = CMS.getConfigStore(); 1586 IConfigStore kgConfig = config.getSubStore("kra.keygen"); 1587 boolean tp = false; 1588 boolean sp = false; 1589 boolean ep = false; 1590 - if (kgConfig != null) { 1591 + if ((kgConfig != null) && (!kgConfig.equals(""))) { 1592 try { 1593 tp = kgConfig.getBoolean("temporaryPairs", false); 1594 sp = kgConfig.getBoolean("sensitivePairs", false); 1595 ep = kgConfig.getBoolean("extractablePairs", false); 1596 // by default, let nethsm work 1597 + CMS.debug("NetkeyKeygenService: found config store: kra.keygen"); 1598 + // by default, let nethsm work 1599 if ((tp == false) && (sp == false) && (ep == false)) { 1600 tp = true; 1601 + if (kpAlg == KeyPairAlgorithm.EC) { 1602 + // set to what works for nethsm 1603 + tp = true; 1604 + sp = false; 1605 + ep = true; 1606 + } 1607 } 1608 } catch (Exception e) { 1609 CMS.debug("NetkeyKeygenService: kgConfig.getBoolean failed"); 1610 @@ -189,69 +201,109 @@ 1611 // by default, let nethsm work 1612 CMS.debug("NetkeyKeygenService: cannot find config store: kra.keygen, assume temporaryPairs==true"); 1613 tp = true; 1614 + if (kpAlg == KeyPairAlgorithm.EC) { 1615 + // set to what works for nethsm 1616 + tp = true; 1617 + sp = false; 1618 + ep = true; 1619 + } 1620 } 1621 - / only specified to "true" will it be set / 1622 - if (tp == true) { 1623 - CMS.debug("NetkeyKeygenService: setting temporaryPairs to true"); 1624 - kpGen.temporaryPairs(true); 1625 - } 1626 - if (sp == true) { 1627 - CMS.debug("NetkeyKeygenService: setting sensitivePairs to true"); 1628 - kpGen.sensitivePairs(true); 1629 - } 1630 - if (ep == true) { 1631 - CMS.debug("NetkeyKeygenService: setting extractablePairs to true"); 1632 - kpGen.extractablePairs(true); 1633 - } 1634 + 1635 + if (kpAlg == KeyPairAlgorithm.EC) { 1636 + 1637 + boolean isECDHE = false; 1638 + KeyPair pair = null; 1639 + 1640 + // used with isECDHE == true 1641 + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask_ECDSA[] = { 1642 + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.DERIVE 1643 + }; 1644 + 1645 + // used with isECDHE == false 1646 + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask_ECDH[] = { 1647 + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN, 1648 + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN_RECOVER 1649 + }; 1650 + 1651 + try { 1652 + pair = CryptoUtil.generateECCKeyPair(token.getName(), /ECC_curve default/ keyCurve , 1653 + null, 1654 + (isECDHE==true) ? usages_mask_ECDSA: usages_mask_ECDH, 1655 + tp /temporary/, sp? 1:0 /sensitive/, ep? 1:0 /extractable/); 1656 + CMS.debug("NetkeyKeygenService: after key pair generation" ); 1657 + } catch (Exception e) { 1658 + CMS.debug("NetkeyKeygenService: key pair generation with exception:"+e.toString()); 1659 + } 1660 + return pair; 1661 + 1662 + } else { // !EC 1663 + //only specified to "true" will it be set 1664 + if (tp == true) { 1665 + CMS.debug("NetkeyKeygenService: setting temporaryPairs to true"); 1666 + kpGen.temporaryPairs(true); 1667 + } 1668 + 1669 + if (sp == true) { 1670 + CMS.debug("NetkeyKeygenService: setting sensitivePairs to true"); 1671 + kpGen.sensitivePairs(true); 1672 + } 1673 + 1674 + if (ep == true) { 1675 + CMS.debug("NetkeyKeygenService: setting extractablePairs to true"); 1676 + kpGen.extractablePairs(true); 1677 + } 1678 1679 - if (kpAlg == KeyPairAlgorithm.DSA) { 1680 - if (pqg == null) { 1681 + if (kpAlg == KeyPairAlgorithm.DSA) { 1682 + if (pqg == null) { 1683 + kpGen.initialize(keySize); 1684 + } else { 1685 + kpGen.initialize(pqg); 1686 + } 1687 + } else { 1688 kpGen.initialize(keySize); 1689 - } else { 1690 - kpGen.initialize(pqg); 1691 } 1692 - } else { 1693 - kpGen.initialize(keySize); 1694 - } 1695 1696 - if (pqg == null) { 1697 - KeyPair kp = null; 1698 - synchronized (new Object()) { 1699 - CMS.debug("NetkeyKeygenService: key pair generation begins"); 1700 - kp = kpGen.genKeyPair(); 1701 - CMS.debug("NetkeyKeygenService: key pair generation done"); 1702 - mKRA.addEntropy(true); 1703 - } 1704 - return kp; 1705 - } else { 1706 - // DSA 1707 - KeyPair kp = null; 1708 + if (pqg == null) { 1709 + KeyPair kp = null; 1710 + synchronized (new Object()) { 1711 + CMS.debug("NetkeyKeygenService: key pair generation begins"); 1712 + kp = kpGen.genKeyPair(); 1713 + CMS.debug("NetkeyKeygenService: key pair generation done"); 1714 + mKRA.addEntropy(true); 1715 + } 1716 + return kp; 1717 + } else { 1718 + // DSA 1719 + KeyPair kp = null; 1720 1721 - / no DSA for now... netkey prototype 1722 - do { 1723 - // 602548 NSS bug - to overcome it, we use isBadDSAKeyPair 1724 - kp = kpGen.genKeyPair(); 1725 + / no DSA for now... netkey prototype 1726 + do { 1727 + // 602548 NSS bug - to overcome it, we use isBadDSAKeyPair 1728 + kp = kpGen.genKeyPair(); 1729 + } 1730 + while (isBadDSAKeyPair(kp)); 1731 + / 1732 + return kp; 1733 } 1734 - while (isBadDSAKeyPair(kp)); 1735 - / 1736 - return kp; 1737 } 1738 } 1739 1740 1741 1742 public KeyPair generateKeyPair( String alg, 1743 - int keySize, PQGParams pqg) throws EBaseException { 1744 + int keySize, String keyCurve, PQGParams pqg) throws EBaseException { 1745 1746 KeyPairAlgorithm kpAlg = null; 1747 1748 if (alg.equals("RSA")) 1749 kpAlg = KeyPairAlgorithm.RSA; 1750 + else if (alg.equals("EC")) 1751 + kpAlg = KeyPairAlgorithm.EC; 1752 else 1753 kpAlg = KeyPairAlgorithm.DSA; 1754 1755 try { 1756 - KeyPair kp = generateKeyPair( kpAlg, keySize, pqg); 1757 + KeyPair kp = generateKeyPair( kpAlg, keySize, keyCurve, pqg); 1758 1759 return kp; 1760 } catch (InvalidParameterException e) { 1761 @@ -324,7 +376,7 @@ 1762 byte[] wrapped_des_key; 1763 1764 byte iv[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}; 1765 - String iv_s =""; 1766 + String iv_s =""; 1767 try { 1768 SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); 1769 random.nextBytes(iv); 1770 @@ -332,34 +384,35 @@ 1771 CMS.debug("NetkeyKeygenService.serviceRequest: "+ e.toString()); 1772 } 1773 1774 - IVParameterSpec algParam = new IVParameterSpec(iv); 1775 + IVParameterSpec algParam = new IVParameterSpec(iv); 1776 1777 wrapped_des_key = null; 1778 - boolean archive = true; 1779 - PK11SymKey sk= null; 1780 - byte[] publicKeyData = null;; 1781 - String PubKey = ""; 1782 + boolean archive = true; 1783 + PK11SymKey sk= null; 1784 + byte[] publicKeyData = null;; 1785 + String PubKey = ""; 1786 1787 String id = request.getRequestId().toString(); 1788 if (id != null) { 1789 auditArchiveID = id.trim(); 1790 } 1791 1792 - String rArchive = request.getExtDataInString(IRequest.NETKEY_ATTR_ARCHIVE_FLAG); 1793 - if (rArchive.equals("true")) { 1794 - archive = true; 1795 + String rArchive = request.getExtDataInString(IRequest.NETKEY_ATTR_ARCHIVE_FLAG); 1796 + if (rArchive.equals("true")) { 1797 + archive = true; 1798 CMS.debug("NetkeyKeygenService: serviceRequest " +"archival requested for serverSideKeyGen"); 1799 - } else { 1800 - archive = false; 1801 + } else { 1802 + archive = false; 1803 CMS.debug("NetkeyKeygenService: serviceRequest " +"archival not requested for serverSideKeyGen"); 1804 } 1805 1806 String rCUID = request.getExtDataInString(IRequest.NETKEY_ATTR_CUID); 1807 String rUserid = request.getExtDataInString(IRequest.NETKEY_ATTR_USERID); 1808 - String rKeysize = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_SIZE); 1809 - int keysize = Integer.parseInt(rKeysize); 1810 - auditSubjectID=rCUID+":"+rUserid; 1811 1812 + String rKeytype = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_TYPE); 1813 + 1814 + auditSubjectID=rCUID+":"+rUserid; 1815 + 1816 SessionContext sContext = SessionContext.getContext(); 1817 String agentId=""; 1818 if (sContext != null) { 1819 @@ -381,15 +434,41 @@ 1820 wrapped_des_key = com.netscape.cmsutil.util.Utils.SpecialDecode(rWrappedDesKeyString); 1821 CMS.debug("NetkeyKeygenService: wrapped_des_key specialDecoded"); 1822 1823 - // get the token for generating user keys 1824 - CryptoToken keygenToken = mKRA.getKeygenToken(); 1825 - if (keygenToken == null) { 1826 - CMS.debug("NetkeyKeygenService: failed getting keygenToken"); 1827 - request.setExtData(IRequest.RESULT, Integer.valueOf(10)); 1828 - return false; 1829 - } else 1830 - CMS.debug("NetkeyKeygenService: got keygenToken"); 1831 +/ 1832 + if ((rKeytype == null) || (rKeytype.equals(""))) { 1833 + rKeytype = "RSA"; 1834 + } 1835 +/ 1836 1837 + if ((rKeytype == null) || (rKeytype.equals(""))) { 1838 + CMS.debug("NetkeyKeygenService: serviceRequest: key type is null"); 1839 + rKeytype = "RSA"; 1840 + } else 1841 + CMS.debug("NetkeyKeygenService: serviceRequest: key type = "+ rKeytype); 1842 + 1843 + / for EC, keysize is ignored, only key curve is used / 1844 + String rKeysize = "2048"; 1845 + int keysize = 2048; 1846 + String rKeycurve = "nistp256"; 1847 + if (rKeytype.equals("EC")) { 1848 + rKeycurve = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_EC_CURVE); 1849 + if ((rKeycurve == null) || (rKeycurve.equals(""))) { 1850 + rKeycurve = "nistp256"; 1851 + } 1852 + } else { 1853 + rKeysize = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_SIZE); 1854 + keysize = Integer.parseInt(rKeysize); 1855 + } 1856 + 1857 + // get the token for generating user keys 1858 + CryptoToken keygenToken = mKRA.getKeygenToken(); 1859 + if (keygenToken == null) { 1860 + CMS.debug("NetkeyKeygenService: failed getting keygenToken"); 1861 + request.setExtData(IRequest.RESULT, Integer.valueOf(10)); 1862 + return false; 1863 + } else 1864 + CMS.debug("NetkeyKeygenService: got keygenToken"); 1865 + 1866 if ((wrapped_des_key != null) && 1867 (wrapped_des_key.length > 0)) { 1868 1869 @@ -401,8 +480,10 @@ 1870 1871 CMS.debug("NetkeyKeygenService: about to generate key pair"); 1872 1873 - keypair = generateKeyPair("RSA"/alg/, 1874 - keysize /Integer.parseInt(len)/, null /pqgParams/); 1875 + keypair = generateKeyPair(rKeytype / rKeytype: "RSA" or "EC" /, 1876 + keysize /Integer.parseInt(len)/, 1877 + rKeycurve / for "EC" only /, 1878 + null /pqgParams/); 1879 1880 if (keypair == null) { 1881 CMS.debug("NetkeyKeygenService: failed generating key pair for "+rCUID+":"+rUserid); 1882 @@ -421,18 +502,20 @@ 1883 CMS.debug("NetkeyKeygenService: finished generate key pair for " +rCUID+":"+rUserid); 1884 1885 try { 1886 - publicKeyData = keypair.getPublic().getEncoded(); 1887 - if (publicKeyData == null) { 1888 - request.setExtData(IRequest.RESULT, Integer.valueOf(4)); 1889 - CMS.debug("NetkeyKeygenService: failed getting publickey encoded"); 1890 - return false; 1891 - } else { 1892 - //CMS.debug("NetkeyKeygenService: public key binary length ="+ publicKeyData.length); 1893 - PubKey = base64Encode(publicKeyData); 1894 + publicKeyData = keypair.getPublic().getEncoded(); 1895 + if (publicKeyData == null) { 1896 + request.setExtData(IRequest.RESULT, Integer.valueOf(4)); 1897 + CMS.debug("NetkeyKeygenService: failed getting publickey encoded"); 1898 + return false; 1899 + } else { 1900 + //CMS.debug("NetkeyKeygenService: public key binary length ="+ publicKeyData.length); 1901 + / url encode / 1902 + PubKey = com.netscape.cmsutil.util.Utils.SpecialEncode(publicKeyData); 1903 + CMS.debug("NetkeyKeygenService: EC PubKey special encoded"); 1904 1905 - //CMS.debug("NetkeyKeygenService: public key length =" + PubKey.length()); 1906 - request.setExtData("public_key", PubKey); 1907 - } 1908 + //CMS.debug("NetkeyKeygenService: public key length =" + PubKey.length()); 1909 + request.setExtData("public_key", PubKey); 1910 + } 1911 1912 auditMessage = CMS.getLogMessage( 1913 LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS, 1914 @@ -558,18 +641,52 @@ 1915 CMS.debug("NetkeyKeygenService: privatekey recording failed"); 1916 return false; 1917 } else 1918 - CMS.debug("NetkeyKeygenService: got key record"); 1919 + CMS.debug("NetkeyKeygenService: got key record"); 1920 1921 - // we deal with RSA key only 1922 - try { 1923 - RSAPublicKey rsaPublicKey = new RSAPublicKey(publicKeyData); 1924 + if (rKeytype.equals("RSA")) { 1925 + try { 1926 + RSAPublicKey rsaPublicKey = new RSAPublicKey(publicKeyData); 1927 1928 - rec.setKeySize(Integer.valueOf(rsaPublicKey.getKeySize())); 1929 - } catch (InvalidKeyException e) { 1930 - request.setExtData(IRequest.RESULT, Integer.valueOf(11)); 1931 - CMS.debug("NetkeyKeygenService: failed:InvalidKeyException"); 1932 - return false; 1933 - } 1934 + rec.setKeySize(Integer.valueOf(rsaPublicKey.getKeySize())); 1935 + } catch (InvalidKeyException e) { 1936 + request.setExtData(IRequest.RESULT, Integer.valueOf(11)); 1937 + CMS.debug("NetkeyKeygenService: failed:InvalidKeyException"); 1938 + return false; 1939 + } 1940 + } else if (rKeytype.equals("EC")) { //cfu 1941 + CMS.debug("NetkeyKeygenService: alg is EC"); 1942 + String oidDescription = "UNDETERMINED"; 1943 + // for KeyRecordParser 1944 + MetaInfo metaInfo = new MetaInfo(); 1945 + 1946 + try { 1947 + byte curve[] = 1948 + ASN1Util.getECCurveBytesByX509PublicKeyBytes(publicKeyData, 1949 + false / without tag and size /); 1950 + if (curve.length != 0) { 1951 + oidDescription = ASN1Util.getOIDdescription(curve); 1952 + } else { 1953 + / this is to be used by derdump / 1954 + byte curveTS[] = 1955 + ASN1Util.getECCurveBytesByX509PublicKeyBytes(publicKeyData, 1956 + true / with tag and size */); 1957 + if (curveTS.length != 0) { 1958 + oidDescription = CMS.BtoA(curveTS); 1959 + } 1960 + } 1961 + } catch (Exception e) { 1962 + CMS.debug("NetkeyKeygenService: ASN1Util.getECCurveBytesByX509PublicKeyByte() throws exception: "+ e.toString()); 1963 + CMS.debug("NetkeyKeygenService: exception allowed. continue"); 1964 + } 1965 + 1966 + metaInfo.set(KeyRecordParser.OUT_KEY_EC_CURVE, 1967 + oidDescription); 1968 + 1969 + rec.set(IKeyRecord.ATTR_META_INFO, metaInfo); 1970 + // key size does not apply to EC; 1971 + rec.setKeySize(-1); 1972 + } 1973 + 1974 //?? 1975 IKeyRepository storage = mKRA.getKeyRepository(); 1976 BigInteger serialNo = storage.getNextSerialNumber();
TPS ECC infrastructure TPS-ECC.forReview2
Index: common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java 2 =================================================================== 3 --- common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java (revision 2471) 4 +++ common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java (working copy) 5 @@ -24,6 +24,7 @@ 6 import javax.servlet.http.; 7 8 import java.io.; 9 +import java.util.Hashtable; 10 11 import com.netscape.certsrv.common.; 12 import com.netscape.certsrv.request.; 13 @@ -55,6 +56,7 @@ 14 IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":"); 15 protected IAuthSubsystem mAuthSubsystem = null; 16 protected ILogger mLogger = CMS.getLogger(); 17 + Hashtable supportedECCurves_ht = null; 18 19 / 20 * Constructs GenerateKeyPair servlet. 21 @@ -67,6 +69,7 @@ 22 public void init(ServletConfig config) throws ServletException { 23 super.init(config); 24 mConfig = config; 25 + IConfigStore sconfig = CMS.getConfigStore(); 26 String authority = config.getInitParameter(PROP_AUTHORITY); 27 28 if (authority != null) 29 @@ -74,6 +77,22 @@ 30 CMS.getSubsystem(authority); 31 32 mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); 33 + 34 + // supported EC cuves by the smart cards 35 + String curveList = null; 36 + try { 37 + curveList = sconfig.getString("kra.keygen.curvelist", 38 + "nistp256,nistp384,nistp521"); 39 + } catch (EBaseException e) { 40 + curveList = "nistp256,nistp384,nistp521"; 41 + } 42 + 43 + supportedECCurves_ht = new Hashtable(); 44 + String[] supportedECCurves = curveList.split(","); 45 + for ( int i = 0; i < supportedECCurves.length; i++) { 46 + supportedECCurves_ht.put(supportedECCurves[i], supportedECCurves[i]); 47 + } 48 + 49 } 50 51 / 52 @@ -113,8 +132,10 @@ 53 String rCUID = req.getParameter("CUID"); 54 String rUserid = req.getParameter("userid"); 55 String rdesKeyString = req.getParameter("drm_trans_desKey"); 56 - String rArchive = req.getParameter("archive"); 57 - String rKeysize = req.getParameter("keysize"); 58 + String rArchive = req.getParameter("archive"); 59 + String rKeysize = req.getParameter("keysize"); 60 + String rKeytype = req.getParameter("keytype"); 61 + String rKeycurve = req.getParameter("eckeycurve"); 62 63 if ((rCUID == null) || (rCUID.equals(""))) { 64 CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: CUID"); 65 @@ -126,10 +147,30 @@ 66 missingParam = true; 67 } 68 69 - if ((rKeysize == null) || (rKeysize.equals(""))) { 70 - rKeysize = "1024"; // default to 1024 71 - } 72 + // keysize is for non-EC (EC uses keycurve) 73 + if (!rKeytype.equals("EC") && ((rKeysize == null) || (rKeysize.equals("")))) { 74 + rKeysize = "1024"; // default to 1024 75 + } 76 77 + // if not specified, default to RSA 78 + if ((rKeytype == null) || (rKeytype.equals(""))) { 79 + rKeytype = "RSA"; 80 + } 81 + 82 + if (rKeytype.equals("EC")) { 83 + if ((rKeycurve == null) || (rKeycurve.equals(""))) { 84 + rKeycurve = "nistp256"; 85 + } 86 + // is the specified curve supported? 87 + boolean isSupportedCurve = supportedECCurves_ht.containsKey(rKeycurve); 88 + if (isSupportedCurve == false) { 89 + CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): unsupported curve:"+ rKeycurve); 90 + missingParam = true; 91 + } else { 92 + CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): curve to be generated:"+ rKeycurve); 93 + } 94 + } 95 + 96 if ((rdesKeyString == null) || 97 (rdesKeyString.equals(""))) { 98 CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: DRM-transportKey-wrapped DES key"); 99 @@ -138,7 +179,7 @@ 100 101 if ((rArchive == null) || (rArchive.equals(""))) { 102 CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing key archival flag 'archive' ,default to true"); 103 - rArchive = "true"; 104 + rArchive = "true"; 105 } 106 107 String selectedToken = null; 108 @@ -150,17 +191,19 @@ 109 thisreq.setExtData(IRequest.NETKEY_ATTR_CUID, rCUID); 110 thisreq.setExtData(IRequest.NETKEY_ATTR_USERID, rUserid); 111 thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, rdesKeyString); 112 - thisreq.setExtData(IRequest.NETKEY_ATTR_ARCHIVE_FLAG, rArchive); 113 - thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_SIZE, rKeysize); 114 + thisreq.setExtData(IRequest.NETKEY_ATTR_ARCHIVE_FLAG, rArchive); 115 + thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_SIZE, rKeysize); 116 + thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_TYPE, rKeytype); 117 + thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_EC_CURVE, rKeycurve); 118 119 queue.processRequest( thisreq ); 120 Integer result = thisreq.getExtDataInInteger(IRequest.RESULT); 121 if (result != null) { 122 - // sighs! tps thinks 0 is good, and DRM thinks 1 is good 123 - if (result.intValue() == 1) 124 - status = "0"; 125 - else 126 - status = result.toString(); 127 + // sighs! tps thinks 0 is good, and DRM thinks 1 is good 128 + if (result.intValue() == 1) 129 + status = "0"; 130 + else 131 + status = result.toString(); 132 } else 133 status = "7"; 134 135 @@ -183,7 +226,7 @@ 136 publicKeyString = thisreq.getExtDataInString("public_key"); 137 wrappedPrivKeyString = thisreq.getExtDataInString("wrappedUserPrivate"); 138 139 - String ivString = thisreq.getExtDataInString("iv_s"); 140 + String ivString = thisreq.getExtDataInString("iv_s"); 141 142 / 143 if (selectedToken == null) 144 @@ -194,12 +237,12 @@ 145 else { 146 StringBuffer sb = new StringBuffer(); 147 sb.append("status=0&"); 148 - sb.append("wrapped_priv_key="); 149 - sb.append(wrappedPrivKeyString); 150 - sb.append("&iv_param="); 151 - sb.append(ivString); 152 + sb.append("wrapped_priv_key="); 153 + sb.append(wrappedPrivKeyString); 154 + sb.append("&iv_param="); 155 + sb.append(ivString); 156 sb.append("&public_key="); 157 - sb.append(publicKeyString); 158 + sb.append(publicKeyString); 159 value = sb.toString(); 160 161 } 162 @@ -267,9 +310,9 @@ 163 } 164 165 // begin Netkey serverSideKeyGen and archival 166 - CMS.debug("GenerateKeyPairServlet: processServerSideKeyGen would be called"); 167 - processServerSideKeyGen(req, resp); 168 - return; 169 + CMS.debug("GenerateKeyPairServlet: processServerSideKeyGen would be called"); 170 + processServerSideKeyGen(req, resp); 171 + return; 172 // end Netkey functions 173 174 } 175 Index: common/src/com/netscape/certsrv/request/IRequest.java 176 =================================================================== 177 --- common/src/com/netscape/certsrv/request/IRequest.java (revision 2471) 178 +++ common/src/com/netscape/certsrv/request/IRequest.java (working copy) 179 @@ -153,6 +153,8 @@ 180 public final static String NETKEY_ATTR_ENC_PRIVKEY_FLAG ="encryptPrivKey"; 181 public final static String NETKEY_ATTR_USER_CERT = "cert"; 182 public final static String NETKEY_ATTR_KEY_SIZE = "keysize"; 183 + public final static String NETKEY_ATTR_KEY_TYPE = "keytype"; 184 + public final static String NETKEY_ATTR_KEY_EC_CURVE = "eckeycurve"; 185 186 // requestor type values. 187 public static final String REQUESTOR_EE = "EE"; 188 Index: tps/src/processor/RA_Enroll_Processor.cpp 189 =================================================================== 190 --- tps/src/processor/RA_Enroll_Processor.cpp (revision 2471) 191 +++ tps/src/processor/RA_Enroll_Processor.cpp (working copy) 192 @@ -184,7 +184,7 @@ 193 const char cert_attr_id, 194 const char pri_attr_id, 195 const char pub_attr_id, 196 - BYTE se_p1, BYTE se_p2, int keysize, const char connid, const char keyTypePrefix,char * applet_version) 197 + BYTE se_p1, BYTE se_p2, BYTE algorithm, int keysize, const char connid, const char keyTypePrefix,char * applet_version) 198 { 199 RA_Status status = STATUS_NO_ERROR; 200 int rc = -1; 201 @@ -231,6 +231,9 @@ 202 RA::Debug(LL_PER_CONNECTION,FN, 203 "Start of keygen/certificate enrollment"); 204 205 + bool isECC = RA::isAlgorithmECC(algorithm); 206 + SECKEYECParams eccParams = NULL; 207 + 208 // get key version for audit logs 209 if (channel != NULL) { 210 if( keyVersion != NULL ) { 211 @@ -288,8 +291,8 @@ 212 (progress_block_size * 15/100) / progress /, 213 "PROGRESS_KEY_GENERATION"); 214 215 - if (key_type == KEY_TYPE_ENCRYPTION) {// do serverSide keygen? 216 - 217 + if (key_type == KEY_TYPE_ENCRYPTION) { 218 + // do serverSide keygen? 219 PR_snprintf((char )configname, 256, "%s.serverKeygen.enable", keyTypePrefix); 220 RA::Debug(LL_PER_CONNECTION,FN, 221 "looking for config %s", configname); 222 @@ -300,57 +303,58 @@ 223 224 if (serverKeygen) { 225 RA::Debug(LL_PER_CONNECTION,FN, 226 - "Private key is to be generated on server"); 227 + "Private key is to be generated on server"); 228 229 PR_snprintf((char )configname, 256, "%s.serverKeygen.drm.conn", keyTypePrefix); 230 RA::Debug(LL_PER_CONNECTION,FN, 231 - "looking for config %s", configname); 232 + "looking for config %s", configname); 233 drmconnid = RA::GetConfigStore()->GetConfigAsString(configname); 234 235 PR_snprintf((char )configname, 256, "%s.serverKeygen.archive", keyTypePrefix); 236 bool archive = RA::GetConfigStore()->GetConfigAsBool(configname, true); 237 238 RA::Debug(LL_PER_CONNECTION,FN, 239 - "calling ServerSideKeyGen with userid =%s, archive=%s", userid, archive? "true":"false"); 240 + "calling ServerSideKeyGen with userid =%s, archive=%s", userid, archive? "true":"false"); 241 242 RA::ServerSideKeyGen(session, cuid, userid, 243 channel->getDrmWrappedDESKey(), &pKey, 244 &wrappedPrivKey, &ivParam, drmconnid, 245 - archive, keysize); 246 + archive, keysize, isECC); 247 248 if (pKey == NULL) { 249 - RA::Error(LL_PER_CONNECTION,FN, 250 - "Failed to generate key on server. Please check DRM."); 251 - RA::Debug(LL_PER_CONNECTION,FN, 252 - "ServerSideKeyGen called, pKey is NULL"); 253 - status = STATUS_ERROR_MAC_ENROLL_PDU; 254 + RA::Error(LL_PER_CONNECTION,FN, 255 + "Failed to generate key on server. Please check DRM."); 256 + RA::Debug(LL_PER_CONNECTION,FN, 257 + "ServerSideKeyGen called, pKey is NULL"); 258 + status = STATUS_ERROR_MAC_ENROLL_PDU; 259 260 PR_snprintf(audit_msg, 512, "ServerSideKeyGen called, failed to generate key on server"); 261 - goto loser; 262 - } else 263 - RA::Debug(LL_PER_CONNECTION,FN, 264 - "key value = %s", pKey); 265 + goto loser; 266 + } else { 267 + RA::Debug(LL_PER_CONNECTION,FN, 268 + "key value = %s", pKey); 269 + } 270 271 272 if (wrappedPrivKey == NULL) { 273 - RA::Debug(LL_PER_CONNECTION,FN, 274 - "ServerSideKeyGen called, wrappedPrivKey is NULL"); 275 - status = STATUS_ERROR_MAC_ENROLL_PDU; 276 + RA::Debug(LL_PER_CONNECTION,FN, 277 + "ServerSideKeyGen called, wrappedPrivKey is NULL"); 278 + status = STATUS_ERROR_MAC_ENROLL_PDU; 279 PR_snprintf(audit_msg, 512, "ServerSideKeyGen called, wrappedPrivKey is NULL"); 280 - goto loser; 281 - } else 282 - RA::Debug(LL_PER_CONNECTION,FN, 283 - "wrappedPrivKey = %s", wrappedPrivKey); 284 + goto loser; 285 + } else { 286 + RA::Debug(LL_PER_CONNECTION,FN, 287 + "wrappedPrivKey = %s", wrappedPrivKey); 288 + } 289 290 if (ivParam == NULL) { 291 - RA::Debug(LL_PER_CONNECTION,FN, 292 - "ServerSideKeyGen called, ivParam is NULL"); 293 - status = STATUS_ERROR_MAC_ENROLL_PDU; 294 + RA::Debug(LL_PER_CONNECTION,FN, 295 + "ServerSideKeyGen called, ivParam is NULL"); 296 + status = STATUS_ERROR_MAC_ENROLL_PDU; 297 PR_snprintf(audit_msg, 512, "ServerSideKeyGen called, ivParam is NULL"); 298 - goto loser; 299 + goto loser; 300 } else 301 - RA::Debug(LL_PER_CONNECTION,FN, 302 - "ivParam = %s", ivParam); 303 + RA::Debug(LL_PER_CONNECTION,FN, "ivParam = %s", ivParam); 304 305 / 306 * the following code converts b64-encoded public key info into SECKEYPublicKey 307 @@ -359,39 +363,46 @@ 308 SECItem der; 309 CERTSubjectPublicKeyInfo spki = NULL; 310 311 + Buffer decodePubKey = Util::URLDecode(pKey); 312 + char pKey_ascii = NULL; 313 + if (decodePubKey != NULL) { 314 + pKey_ascii = 315 + BTOA_DataToAscii(decodePubKey->getBuf(), decodePubKey->getLen()); 316 + } else { 317 + PR_snprintf(audit_msg, 512, "ServerSideKeyGen: failed to URL decode public key"); 318 + goto loser; 319 + } 320 + 321 der.type = (SECItemType) 0; / initialize it, since convertAsciiToItem does not set it / 322 - rv = ATOB_ConvertAsciiToItem (&der, pKey); 323 + rv = ATOB_ConvertAsciiToItem (&der, pKey_ascii); 324 if (rv != SECSuccess){ 325 - RA::Debug(LL_PER_CONNECTION,FN, 326 - "failed to convert b64 private key to binary"); 327 - SECITEM_FreeItem(&der, PR_FALSE); 328 - status = STATUS_ERROR_MAC_ENROLL_PDU; 329 - PR_snprintf(audit_msg, 512, "ServerSideKeyGen: failed to convert b64 private key to binary"); 330 - goto loser; 331 - }else { 332 - RA::Debug(LL_PER_CONNECTION,FN, 333 - "decoded private key as: secitem (len=%d)",der.len); 334 + RA::Debug(LL_PER_CONNECTION,FN, 335 + "failed to convert b64 public key to binary"); 336 + SECITEM_FreeItem(&der, PR_FALSE); 337 + status = STATUS_ERROR_MAC_ENROLL_PDU; 338 + PR_snprintf(audit_msg, 512, "ServerSideKeyGen: failed to convert b64 public key to binary"); 339 + goto loser; 340 + } else { 341 + RA::Debug(LL_PER_CONNECTION,FN, 342 + "decoded public key as: secitem (len=%d)",der.len); 343 344 - spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der); 345 + spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&der); 346 347 - if (spki != NULL) { 348 - RA::Debug(LL_PER_CONNECTION,FN, 349 - "Successfully decoded DER SubjectPublicKeyInfo structure"); 350 - pk_p = SECKEY_ExtractPublicKey(spki); 351 - if (pk_p != NULL) 352 - RA::Debug(LL_PER_CONNECTION,FN, 353 - "Successfully extracted public key from SPKI structure"); 354 - else 355 - RA::Debug(LL_PER_CONNECTION,FN, 356 - "Failed to extract public key from SPKI"); 357 - } else { 358 - RA::Debug(LL_PER_CONNECTION,FN, 359 - "Failed to decode SPKI structure"); 360 - } 361 + if (spki != NULL) { 362 + RA::Debug(LL_PER_CONNECTION,FN, 363 + "Successfully decoded DER SubjectPublicKeyInfo structure"); 364 + pk_p = SECKEY_ExtractPublicKey(spki); 365 + if (pk_p != NULL) 366 + RA::Debug(LL_PER_CONNECTION,FN, "Successfully extracted public key from SPKI structure"); 367 + else 368 + RA::Debug(LL_PER_CONNECTION,FN, "Failed to extract public key from SPKI"); 369 + } else { 370 + RA::Debug(LL_PER_CONNECTION,FN, 371 + "Failed to decode SPKI structure"); 372 + } 373 374 - SECITEM_FreeItem(&der, PR_FALSE); 375 - SECKEY_DestroySubjectPublicKeyInfo(spki); 376 - 377 + SECITEM_FreeItem(&der, PR_FALSE); 378 + SECKEY_DestroySubjectPublicKeyInfo(spki); 379 } 380 381 } else { //generate keys on token 382 @@ -404,6 +415,11 @@ 383 if(key_check && key_check->size()) 384 alg = 0x81; 385 386 + 387 + if (isECC) { 388 + alg = algorithm; 389 + } 390 + 391 len = channel->StartEnrollment( 392 se_p1, se_p2, 393 wrapped_challenge, 394 @@ -412,7 +428,7 @@ 395 0x00 / option /); 396 397 RA::Debug(LL_PER_CONNECTION,FN, 398 - "channel->StartEnrollment returned length of public key blob: len=%d", len); 399 + "channel->StartEnrollment returned length of public key blob: len=%d", len); 400 401 StatusUpdate(session, extensions, 402 start_progress + (index * progress_block_size) + 403 @@ -460,6 +476,8 @@ 404 plaintext_challenge); 405 406 407 + // We have received the public key blob for ECC 408 + 409 // send status update to the client 410 StatusUpdate(session, extensions, 411 start_progress + (index * progress_block_size) + 412 @@ -471,7 +489,7 @@ 413 414 pk_p = certEnroll->ParsePublicKeyBlob( 415 (unsigned char )(BYTE )public_key /blob/, 416 - plaintext_challenge); 417 + plaintext_challenge, isECC); 418 419 if (pk_p == NULL) { 420 RA::Error(LL_PER_CONNECTION,FN, 421 @@ -550,8 +568,10 @@ 422 goto loser; 423 } 424 425 - si_mod = pk_p->u.rsa.modulus; 426 - modulus = new Buffer((BYTE) si_mod.data, si_mod.len); 427 + if (!isECC) { 428 + si_mod = pk_p->u.rsa.modulus; 429 + modulus = new Buffer((BYTE) si_mod.data, si_mod.len); 430 + } 431 432 / 433 * RFC 3279 434 @@ -569,15 +589,15 @@ 435 si_kid = PK11_MakeIDFromPubKey(&spkix->subjectPublicKey); 436 spkix->subjectPublicKey.len <<= 3; 437 438 - 439 keyid = new Buffer((BYTE) si_kid->data, si_kid->len); 440 441 - si_exp = pk_p->u.rsa.publicExponent; 442 - exponent = new Buffer((BYTE) si_exp.data, si_exp.len); 443 + if (!isECC) { 444 + si_exp = pk_p->u.rsa.publicExponent; 445 + exponent = new Buffer((BYTE) si_exp.data, si_exp.len); 446 + RA::Debug(LL_PER_CONNECTION,FN, 447 + "Keyid, modulus and exponent have been extracted from public key"); 448 + } 449 450 - RA::Debug(LL_PER_CONNECTION,FN, 451 - "Keyid, modulus and exponent have been extracted from public key"); 452 - 453 SECKEY_DestroySubjectPublicKeyInfo(spkix); 454 455 cert_string = (char ) cert->string(); 456 @@ -788,67 +808,77 @@ 457 458 / write certificate from CA to netkey / 459 if (pkcs11obj_enable) { 460 - ObjectSpec objSpec = 461 - ObjectSpec::ParseFromTokenData( 462 - (cert_id[0] << 24) + 463 - (cert_id[1] << 16), 464 - cert); 465 - pkcs_objx->AddObjectSpec(objSpec); 466 + ObjectSpec objSpec = 467 + ObjectSpec::ParseFromTokenData( 468 + (cert_id[0] << 24) + 469 + (cert_id[1] << 16), 470 + cert); 471 + pkcs_objx->AddObjectSpec(objSpec); 472 } else { 473 - RA::Debug(LL_PER_CONNECTION,FN, 474 - "About to create certificate object on token"); 475 - rc = channel->CreateCertificate(cert_id, cert); 476 - if (rc == -1) { 477 - RA::Error(LL_PER_CONNECTION,FN, 478 - "Failed to create certificate object on token"); 479 - status = STATUS_ERROR_MAC_ENROLL_PDU; 480 - PR_snprintf(audit_msg, 512, "Failed to create certificate object on token"); 481 - goto loser; 482 - } 483 + RA::Debug(LL_PER_CONNECTION,FN, 484 + "About to create certificate object on token"); 485 + rc = channel->CreateCertificate(cert_id, cert); 486 + if (rc == -1) { 487 + RA::Error(LL_PER_CONNECTION,FN, 488 + "Failed to create certificate object on token"); 489 + status = STATUS_ERROR_MAC_ENROLL_PDU; 490 + PR_snprintf(audit_msg, 512, "Failed to create certificate object on token"); 491 + goto loser; 492 + } 493 } 494 495 // build label 496 PR_snprintf((char )configname, 256, "%s.%s.keyGen.%s.label", 497 - OP_PREFIX, tokenType, keyType); 498 + OP_PREFIX, tokenType, keyType); 499 RA::Debug(LL_PER_CONNECTION,FN, 500 - "label '%s'", configname); 501 + "label '%s'", configname); 502 pattern = RA::GetConfigStore()->GetConfigAsString(configname); 503 label = MapPattern(&nv, (char ) pattern); 504 505 if (pkcs11obj_enable) { 506 - Buffer b = channel->CreatePKCS11CertAttrsBuffer( 507 - key_type, cert_attr_id, label, keyid); 508 - ObjectSpec objSpec = 509 - ObjectSpec::ParseFromTokenData( 510 - (cert_attr_id[0] << 24) + 511 - (cert_attr_id[1] << 16), 512 - &b); 513 - pkcs_objx->AddObjectSpec(objSpec); 514 + Buffer b = channel->CreatePKCS11CertAttrsBuffer( 515 + key_type, cert_attr_id, label, keyid); 516 + ObjectSpec objSpec = 517 + ObjectSpec::ParseFromTokenData( 518 + (cert_attr_id[0] << 24) + 519 + (cert_attr_id[1] << 16), 520 + &b); 521 + pkcs_objx->AddObjectSpec(objSpec); 522 } else { 523 - RA::Debug(LL_PER_CONNECTION,FN, 524 - "About to create PKCS#11 certificate Attributes"); 525 - rc = channel->CreatePKCS11CertAttrs(key_type, cert_attr_id, label, keyid); 526 - if (rc == -1) { 527 - RA::Error(LL_PER_CONNECTION,FN, 528 - "PKCS11 Certificate attributes creation failed"); 529 - status = STATUS_ERROR_MAC_ENROLL_PDU; 530 + RA::Debug(LL_PER_CONNECTION,FN, 531 + "About to create PKCS#11 certificate Attributes"); 532 + rc = channel->CreatePKCS11CertAttrs(key_type, cert_attr_id, label, keyid); 533 + if (rc == -1) { 534 + RA::Error(LL_PER_CONNECTION,FN, 535 + "PKCS11 Certificate attributes creation failed"); 536 + status = STATUS_ERROR_MAC_ENROLL_PDU; 537 PR_snprintf(audit_msg, 512, "PKCS11 Certificate attributes creation failed"); 538 - goto loser; 539 - } 540 + goto loser; 541 + } 542 } 543 544 if (pkcs11obj_enable) { 545 - RA::Debug(LL_PER_CONNECTION,FN, 546 - "Create PKCS11 Private Key Attributes Buffer"); 547 - Buffer b = channel->CreatePKCS11PriKeyAttrsBuffer(key_type, 548 - pri_attr_id, label, keyid, modulus, OP_PREFIX, 549 - tokenType, keyTypePrefix); 550 - ObjectSpec objSpec = 551 - ObjectSpec::ParseFromTokenData( 552 - (pri_attr_id[0] << 24) + 553 - (pri_attr_id[1] << 16), 554 - &b); 555 - pkcs_objx->AddObjectSpec(objSpec); 556 + RA::Debug(LL_PER_CONNECTION,FN, 557 + "Create PKCS11 Private Key Attributes Buffer"); 558 + 559 + Buffer b; 560 + if (!isECC) { 561 + b = channel->CreatePKCS11PriKeyAttrsBuffer(key_type, 562 + pri_attr_id, label, keyid, modulus, OP_PREFIX, 563 + tokenType, keyTypePrefix); 564 + 565 + } else { //isECC 566 + eccParams = &pk_p->u.ec.DEREncodedParams; 567 + b = channel->CreatePKCS11ECCPriKeyAttrsBuffer(key_type, 568 + pri_attr_id, label, keyid, eccParams, OP_PREFIX, 569 + tokenType, keyTypePrefix); 570 + } 571 + ObjectSpec objSpec = 572 + ObjectSpec::ParseFromTokenData( 573 + (pri_attr_id[0] << 24) + 574 + (pri_attr_id[1] << 16), 575 + &b); 576 + pkcs_objx->AddObjectSpec(objSpec); 577 } else { 578 RA::Debug(LL_PER_CONNECTION,FN, 579 "Create PKCS11 Private Key Attributes"); 580 @@ -863,27 +893,34 @@ 581 } 582 583 if (pkcs11obj_enable) { 584 - Buffer b = channel->CreatePKCS11PubKeyAttrsBuffer(key_type, 585 - pub_attr_id, label, keyid, 586 - exponent, modulus, OP_PREFIX, tokenType, keyTypePrefix); 587 - ObjectSpec objSpec = 588 - ObjectSpec::ParseFromTokenData( 589 - (pub_attr_id[0] << 24) + 590 - (pub_attr_id[1] << 16), 591 - &b); 592 - pkcs_objx->AddObjectSpec(objSpec); 593 + Buffer b; 594 + if (!isECC) { 595 + b = channel->CreatePKCS11PubKeyAttrsBuffer(key_type, 596 + pub_attr_id, label, keyid, 597 + exponent, modulus, OP_PREFIX, tokenType, keyTypePrefix); 598 + } else { 599 + b = channel->CreatePKCS11ECCPubKeyAttrsBuffer(key_type, 600 + pub_attr_id, label, keyid,&pk_p->u.ec, eccParams, 601 + OP_PREFIX, tokenType, keyTypePrefix); 602 + } 603 + ObjectSpec objSpec = 604 + ObjectSpec::ParseFromTokenData( 605 + (pub_attr_id[0] << 24) + 606 + (pub_attr_id[1] << 16), 607 + &b); 608 + pkcs_objx->AddObjectSpec(objSpec); 609 } else { 610 - RA::Debug(LL_PER_CONNECTION,FN, 611 - "Create PKCS11 Public Key Attributes"); 612 - rc = channel->CreatePKCS11PubKeyAttrs(key_type, pub_attr_id, label, keyid, 613 + RA::Debug(LL_PER_CONNECTION,FN, 614 + "Create PKCS11 Public Key Attributes"); 615 + rc = channel->CreatePKCS11PubKeyAttrs(key_type, pub_attr_id, label, keyid, 616 exponent, modulus, OP_PREFIX, tokenType, keyTypePrefix); 617 - if (rc == -1) { 618 - RA::Error(LL_PER_CONNECTION,FN, 619 - "PKCS11 public key attributes creation failed"); 620 - status = STATUS_ERROR_MAC_ENROLL_PDU; 621 + if (rc == -1) { 622 + RA::Error(LL_PER_CONNECTION,FN, 623 + "PKCS11 public key attributes creation failed"); 624 + status = STATUS_ERROR_MAC_ENROLL_PDU; 625 PR_snprintf(audit_msg, 512, "PKCS11 public key attributes creation failed"); 626 - goto loser; 627 - } 628 + goto loser; 629 + } 630 } 631 RA::Debug(LL_PER_CONNECTION,FN, "End of keygen/certificate enrollment"); 632 633 @@ -983,10 +1020,13 @@ 634 } 635 if (pk_p != NULL) { 636 if (serverKeygen) { 637 + RA::Debug(LL_PER_CONNECTION,FN,"DoEnrollment about to call SECKEY_DestroyPublicKey on pk_p"); 638 SECKEY_DestroyPublicKey(pk_p); 639 } else { 640 + RA::Debug(LL_PER_CONNECTION,FN,"DoEnrollment about to call free on pk_p"); 641 free(pk_p); 642 } 643 + 644 pk_p = NULL; 645 } 646 return status; 647 @@ -3055,6 +3095,11 @@ 648 PR_snprintf((char )configname, 256, "%s.keySize", keyTypePrefix); 649 int keySize = RA::GetConfigStore()->GetConfigAsInt(configname, 1024); 650 651 + 652 + PR_snprintf((char )configname, 256, "%s.alg", keyTypePrefix); 653 + //Default RSA_CRT=2 654 + BYTE algorithm = (BYTE) RA::GetConfigStore()->GetConfigAsInt(configname, 2); 655 + 656 PR_snprintf((char )configname, 256, "%s.publisherId", keyTypePrefix); 657 const char publisherId = RA::GetConfigStore()->GetConfigAsString(configname, NULL); 658 659 @@ -3105,7 +3150,7 @@ 660 msn, 661 khex, (TokenKeyType)keyTypeEnum, profileId, userid, certId,publisherId, certAttrId, priKeyAttrId, 662 pubKeyAttrId, (keyUser << 4)+priKeyNumber, 663 - (keyUsage << 4)+pubKeyNumber, keySize, caconnid, keyTypePrefix,(char )final_applet_version); 664 + (keyUsage << 4)+pubKeyNumber, algorithm, keySize, caconnid, keyTypePrefix,(char )final_applet_version); 665 666 if (o_status != STATUS_NO_ERROR) { 667 r = false; 668 Index: tps/src/cms/CertEnroll.cpp 669 =================================================================== 670 --- tps/src/cms/CertEnroll.cpp (revision 2471) 671 +++ tps/src/cms/CertEnroll.cpp (working copy) 672 @@ -19,6 +19,7 @@ 673 // --- END COPYRIGHT BLOCK --- 674 675 #include 676 +#include 677 678 #include "main/RA_Session.h" 679 #include "main/RA_Msg.h" 680 @@ -35,6 +36,7 @@ 681 #include "base64.h" 682 #include "nssb64.h" 683 #include "prlock.h" 684 +#include "secoidt.h" 685 686 #include "main/Memory.h" 687 688 @@ -49,6 +51,131 @@ 689 #define TOKENDB_PUBLIC 690 #endif / !XP_WIN32 / 691 692 +//ECC curve information 693 + 694 +typedef struct curveNameTagPairStr { 695 + char curveName; 696 + SECOidTag curveOidTag; 697 +} CurveNameTagPair; 698 + 699 + 700 +static CurveNameTagPair nameTagPair[] = 701 +{ 702 + { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, 703 + { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, 704 + { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, 705 + { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, 706 + { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, 707 + { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, 708 + { "prime256v1", SEC_OID_ANSIX962_EC_PRIME256V1 }, 709 + 710 + { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, 711 + { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, 712 + { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, 713 + { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, 714 + { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, 715 + { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, 716 + { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, 717 + { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, 718 + { "secp192r1", SEC_OID_ANSIX962_EC_PRIME192V1 }, 719 + { "nistp192", SEC_OID_ANSIX962_EC_PRIME192V1 }, 720 + { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, 721 + { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, 722 + { "nistp224", SEC_OID_SECG_EC_SECP224R1}, 723 + { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, 724 + { "secp256r1", SEC_OID_ANSIX962_EC_PRIME256V1 }, 725 + { "nistp256", SEC_OID_ANSIX962_EC_PRIME256V1 }, 726 + { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, 727 + { "nistp384", SEC_OID_SECG_EC_SECP384R1}, 728 + { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, 729 + { "nistp521", SEC_OID_SECG_EC_SECP521R1}, 730 + 731 + { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, 732 + { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, 733 + { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, 734 + { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, 735 + { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, 736 + { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, 737 + { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, 738 + { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, 739 + { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, 740 + { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, 741 + { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, 742 + { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, 743 + { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, 744 + { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, 745 + { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, 746 + { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, 747 + { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, 748 + { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, 749 + { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, 750 + { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, 751 + 752 + { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, 753 + { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, 754 + { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, 755 + { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, 756 + { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, 757 + { "nistk163", SEC_OID_SECG_EC_SECT163K1}, 758 + { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, 759 + { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, 760 + { "nistb163", SEC_OID_SECG_EC_SECT163R2}, 761 + { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, 762 + { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, 763 + { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, 764 + { "nistk233", SEC_OID_SECG_EC_SECT233K1}, 765 + { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, 766 + { "nistb233", SEC_OID_SECG_EC_SECT233R1}, 767 + { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, 768 + { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, 769 + { "nistk283", SEC_OID_SECG_EC_SECT283K1}, 770 + { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, 771 + { "nistb283", SEC_OID_SECG_EC_SECT283R1}, 772 + { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, 773 + { "nistk409", SEC_OID_SECG_EC_SECT409K1}, 774 + { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, 775 + { "nistb409", SEC_OID_SECG_EC_SECT409R1}, 776 + { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, 777 + { "nistk571", SEC_OID_SECG_EC_SECT571K1}, 778 + { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, 779 + { "nistb571", SEC_OID_SECG_EC_SECT571R1}, 780 + 781 +}; 782 + 783 +SECKEYECParams * 784 +CertEnroll::encode_ec_params(char curve) 785 +{ 786 + SECKEYECParams ecparams; 787 + SECOidData oidData = NULL; 788 + SECOidTag curveOidTag = SEC_OID_UNKNOWN; / default / 789 + int i, numCurves; 790 + 791 + if (curve && curve) { 792 + numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); 793 + for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); 794 + i++) { 795 + if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) 796 + curveOidTag = nameTagPair[i].curveOidTag; 797 + } 798 + } 799 + 800 + if ((curveOidTag == SEC_OID_UNKNOWN) || 801 + (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { 802 + return NULL; 803 + } 804 + 805 + ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); 806 + 807 + if (!ecparams) 808 + return NULL; 809 + 810 + ecparams->data[0] = SEC_ASN1_OBJECT_ID; 811 + ecparams->data[1] = oidData->oid.len; 812 + memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); 813 + 814 + return ecparams; 815 +} 816 + 817 / 818 * Constructs handle for Certificate Enrollment 819 / 820 @@ -328,8 +455,20 @@ 821 * Short Exponent Length 822 * 823 * Byte[] Exponent 824 + * 825 + * 826 + * ECC KeyBlob Format (ECC Public Key) 827 + * ---------------------------------- 828 + * 829 + * Byte Encoding (0 for plaintext) 830 * 831 - * 832 + * Byte Key Type (10 for ECC public) 833 + * 834 + * Short Key Length (256, 384, 521 high byte first) 835 + * 836 + * Byte[] Key (W) 837 + * 838 + * 839 * Signature Format (Proof) 840 * --------------------------------------- 841 * 842 @@ -369,7 +508,7 @@ 843 */ 844 845 SECKEYPublicKey CertEnroll::ParsePublicKeyBlob(unsigned char blob, 846 - Buffer challenge) 847 + Buffer challenge, bool isECC) 848 { 849 char configname[5000]; 850 SECKEYPublicKey pk = NULL; 851 @@ -404,7 +543,7 @@ 852 pkeyb_len = (unsigned short) ((len0 << 8) | (len1 & 0xFF)); 853 854 RA::Debug(LL_PER_PDU, "CertEnroll::ParsePublicKeyBlob", 855 - "pkeyb_len =%d",pkeyb_len); 856 + "pkeyb_len =%d isECC: %d",pkeyb_len, isECC); 857 858 if (pkeyb_len <= 0) { 859 RA::Error("CertEnroll::ParsePublicKeyBlob", "public key blob length = %d", pkeyb_len); 860 @@ -431,51 +570,112 @@ 861 862 // convert pkeyb to pkey 863 // 1 byte encoding, 1 byte key type, 2 bytes key length, then the key 864 + 865 + // for ECC 866 + unsigned short ecc_pkey_len = 0; 867 + // ecc key blob 868 + unsigned char eccpb = NULL; 869 + 870 + // for RSA 871 + unsigned short mod_len = 0; 872 + unsigned short exp_len = 0; 873 + // public key mod blob 874 + unsigned char * modb = NULL; 875 + // public key exp blob 876 + unsigned char * expb = NULL; 877 + 878 unsigned short pkey_offset = 4; 879 - // now, convert lengths for modulus and exponent 880 len0 = pkeyb[pkey_offset]; 881 len1 = pkeyb[pkey_offset + 1]; 882 - unsigned short mod_len = (len0 << 8 | len1); 883 884 - len0 = pkeyb[pkey_offset + 2 + mod_len]; 885 - len1 = pkeyb[pkey_offset + 2 + mod_len + 1]; 886 - unsigned short exp_len = (len0 << 8 | len1); 887 + if (!isECC) { 888 + // now, convert lengths for modulus and exponent 889 + mod_len = (len0 << 8 | len1); 890 891 + len0 = pkeyb[pkey_offset + 2 + mod_len]; 892 + len1 = pkeyb[pkey_offset + 2 + mod_len + 1]; 893 + exp_len = (len0 << 8 | len1); 894 895 - // public key mod blob 896 - unsigned char * modb = &pkeyb[pkey_offset + 2]; 897 + modb = &pkeyb[pkey_offset + 2]; 898 + expb = &pkeyb[pkey_offset + 2 + mod_len + 2]; 899 900 - // public key exp blob 901 - unsigned char * expb = &pkeyb[pkey_offset + 2 + mod_len + 2]; 902 + } else { 903 + ecc_pkey_len = (len0 << 8 | len1); 904 + eccpb = &pkeyb[pkey_offset + 2]; 905 + } 906 907 // construct SECItem 908 + 909 + // for RSA 910 SECItem siMod; 911 - siMod.type = (SECItemType) 0; 912 - siMod.data = (unsigned char ) modb; 913 - siMod.len = mod_len; 914 - 915 SECItem siExp; 916 - siExp.type = (SECItemType) 0; 917 - siExp.data = (unsigned char )expb; 918 - siExp.len = exp_len; 919 - 920 - // construct SECKEYRSAPublicKeyStr 921 SECKEYRSAPublicKeyStr rsa_pks; 922 - rsa_pks.modulus = siMod; 923 - rsa_pks.publicExponent = siExp; 924 925 - // construct SECKEYPublicKey 926 - // this is to be returned 927 + // for ECC 928 + SECItem eccValue; 929 + SECKEYECPublicKeyStr ecc_pks; 930 + SECKEYECParams ecc_key_params = NULL; 931 + 932 pk = (SECKEYPublicKey ) malloc(sizeof(SECKEYPublicKey)); 933 - pk->keyType = rsaKey; 934 - pk->pkcs11Slot = NULL; 935 - pk->pkcs11ID = CK_INVALID_HANDLE; 936 - pk->u.rsa = rsa_pks; 937 938 + assert(pk); 939 + 940 + if (!isECC) { 941 + 942 + siMod.type = (SECItemType) 0; 943 + siMod.data = (unsigned char ) modb; 944 + siMod.len = mod_len; 945 + 946 + siExp.type = (SECItemType) 0; 947 + siExp.data = (unsigned char )expb; 948 + siExp.len = exp_len; 949 + 950 + // construct SECKEYRSAPublicKeyStr 951 + rsa_pks.modulus = siMod; 952 + rsa_pks.publicExponent = siExp; 953 + 954 + pk->keyType = rsaKey; 955 + pk->pkcs11Slot = NULL; 956 + pk->pkcs11ID = CK_INVALID_HANDLE; 957 + pk->u.rsa = rsa_pks; 958 + } else { 959 + // ECC 960 + len0 = blob[pkeyb_len_offset +4]; 961 + len1 = blob[pkeyb_len_offset +5]; 962 + int keyCurveSize = (len0 << 8 | len1); 963 + 964 + RA::Debug(LL_PER_PDU, "CertEnroll::ParsePublicKeyBlob", 965 + "keyCurveSize =%d",keyCurveSize); 966 + 967 + char curve[56] = ""; 968 + snprintf(curve, 56, "nistp%d",keyCurveSize ); 969 + 970 + ecc_key_params = encode_ec_params(curve); 971 + 972 + if (ecc_key_params == NULL) { 973 + free(pk); 974 + pk = NULL; 975 + return NULL; 976 + } 977 + 978 + eccValue.type = (SECItemType) 0; 979 + eccValue.data = (unsigned char ) eccpb; 980 + eccValue.len = ecc_pkey_len; 981 + 982 + ecc_pks.size = keyCurveSize; 983 + ecc_pks.publicValue = eccValue; 984 + ecc_pks.DEREncodedParams = ecc_key_params; 985 + 986 + pk->keyType = ecKey; 987 + pk->pkcs11Slot = NULL; 988 + pk->pkcs11ID = CK_INVALID_HANDLE; 989 + pk->u.ec = ecc_pks; 990 + } 991 + 992 PR_snprintf((char )configname, 256, "general.verifyProof"); 993 int verifyProofEnable = RA::GetConfigStore()->GetConfigAsInt(configname, 0x1); 994 if (verifyProofEnable) { 995 - rs = verifyProof(pk, &siProof, pkeyb_len, pkeyb, challenge); 996 + rs = verifyProof(pk, &siProof, pkeyb_len, pkeyb, challenge, isECC); 997 if (rs.status == PR_FAILURE) { 998 RA::Error("CertEnroll::ParsePublicKeyBlob", 999 "verify proof failed"); 1000 @@ -487,7 +687,33 @@ 1001 return pk; 1002 } 1003 1004 +/ 1005 + * for debugging tokens 1006 + * -- list out all tokens and thier login status 1007 + / 1008 +static SECStatus 1009 +ListModules(void) 1010 +{ 1011 + PK11SlotList list; 1012 + PK11SlotListElement le; 1013 1014 + / get them all! / 1015 + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,NULL); 1016 + if (list == NULL) return SECFailure; 1017 + 1018 + / look at each slot/ 1019 + for (le = list->head ; le; le = le->next) { 1020 + RA::Debug( LL_PER_PDU, "CertEnroll::ListModules", 1021 + " slot: %s\n, loggedIn? %d, token: %s\n", PK11_GetSlotName(le->slot), 1022 + (PK11_IsLoggedIn(le->slot, NULL) == PR_TRUE)? 1:0, 1023 + PK11_GetTokenName(le->slot)); 1024 + } 1025 + PK11_FreeSlotList(list); 1026 + 1027 + return SECSuccess; 1028 +} 1029 + 1030 + 1031 / 1032 * verify the proof. 1033 * @param pk the public key from the input blob 1034 @@ -502,18 +728,24 @@ 1035 / 1036 ReturnStatus CertEnroll::verifyProof(SECKEYPublicKey pk, SECItem siProof, 1037 unsigned short pkeyb_len, unsigned char pkeyb, 1038 - Buffer challenge) { 1039 + Buffer challenge, bool isECC) { 1040 1041 ReturnStatus rs; 1042 VFYContext * vc = NULL; 1043 rs.statusNum = ::VRFY_SUCCESS; 1044 rs.status = PR_SUCCESS; 1045 1046 + // ListModules(); 1047 + 1048 // verify proof (signature) 1049 RA::Debug(LL_PER_PDU, "CertEnroll::verifyProof", 1050 "verify proof begins"); 1051 1052 - vc = VFY_CreateContext(pk, siProof, SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE, NULL); 1053 + if(isECC) { 1054 + vc = VFY_CreateContext(pk, siProof, SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE , NULL); 1055 + } else { 1056 + vc = VFY_CreateContext(pk, siProof, SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE, NULL); 1057 + } 1058 1059 if (vc == NULL) { 1060 RA::Error("CertEnroll::verifyProof", 1061 @@ -530,14 +762,15 @@ 1062 int i =0; 1063 for (i = 0; i<pkeyb_len; i++) { 1064 proof[i] = pkeyb[i]; 1065 + RA::Debug(LL_PER_PDU,"CertEnroll::VerifyProof", "proof[%d]=%x", i, proof[i]); 1066 } 1067 - // RA::DebugBuffer("CertEnroll::VerifyProof","VerifyProof:: challenge =", challenge); 1068 + RA::DebugBuffer("CertEnroll::VerifyProof","VerifyProof:: challenge =", challenge); 1069 unsigned char chal = (unsigned char )(BYTE ) (challenge); 1070 unsigned int j = 0; 1071 for (j=0; j < challenge->size(); i++, j++) { 1072 proof[i] = chal[j]; 1073 - // RA::Debug(LL_PER_PDU, "CertEnroll::VerifyProof","proof[%d]= %x", 1074 - // i, proof[i]); 1075 + RA::Debug(LL_PER_PDU, "CertEnroll::VerifyProof","proof[%d]= %x", 1076 + i, proof[i]); 1077 } 1078 1079 SECStatus vs = VFY_Begin(vc); 1080 @@ -547,7 +780,7 @@ 1081 vs = VFY_End(vc); 1082 if (vs == SECFailure) { 1083 RA::Error("CertEnroll::verifyProof", 1084 - "VFY_End() failed pkeyb_len=%d challenge_size=%d", pkeyb_len, challenge->size()); 1085 + "VFY_End() failed pkeyb_len=%d challenge_size=%d error=%d", pkeyb_len, challenge->size(),PR_GetError()); 1086 rs.statusNum = ::VFY_UPDATE_FAILURE; 1087 rs.status = PR_FAILURE; 1088 } 1089 Index: tps/src/include/processor/RA_Enroll_Processor.h 1090 =================================================================== 1091 --- tps/src/include/processor/RA_Enroll_Processor.h (revision 2471) 1092 +++ tps/src/include/processor/RA_Enroll_Processor.h (working copy) 1093 @@ -50,40 +50,40 @@ 1094 1095 class RA_Enroll_Processor : public RA_Processor 1096 { 1097 - public: 1098 - TPS_PUBLIC RA_Enroll_Processor(); 1099 - TPS_PUBLIC ~RA_Enroll_Processor(); 1100 - public: 1101 - int ParsePublicKeyBlob(unsigned char blob, 1102 - unsigned char challenge, 1103 - SECKEYPublicKey pk); 1104 - RA_Status DoEnrollment(AuthParams login, RA_Session session, 1105 - CERTCertificate certificates, 1106 - char origins, 1107 - char ktypes, 1108 - int pkcs11obj, 1109 - PKCS11Obj * pkcs_objx, 1110 - NameValueSet extensions, 1111 - int index, int keyTypeNum, 1112 - int start_progress, 1113 - int end_progress, 1114 - Secure_Channel channel, Buffer wrapped_challenge, 1115 - const char tokenType, 1116 - const char keyType, 1117 - Buffer key_check, 1118 - Buffer plaintext_challenge, 1119 - const char cuid, 1120 - const char msn, 1121 - const char khex, 1122 - TokenKeyType key_type, 1123 - const char profileId, 1124 - const char userid, 1125 - const char cert_id, 1126 - const char publisher_id, 1127 - const char cert_attr_id, 1128 - const char pri_attr_id, 1129 - const char pub_attr_id, 1130 - BYTE se_p1, BYTE se_p2, int keysize, const char connid, const char keyTypePrefix,char * applet_version); 1131 + public: 1132 + TPS_PUBLIC RA_Enroll_Processor(); 1133 + TPS_PUBLIC ~RA_Enroll_Processor(); 1134 + public: 1135 + int ParsePublicKeyBlob(unsigned char blob, 1136 + unsigned char challenge, 1137 + SECKEYPublicKey pk); 1138 + RA_Status DoEnrollment(AuthParams login, RA_Session session, 1139 + CERTCertificate certificates, 1140 + char origins, 1141 + char ktypes, 1142 + int pkcs11obj, 1143 + PKCS11Obj * pkcs_objx, 1144 + NameValueSet extensions, 1145 + int index, int keyTypeNum, 1146 + int start_progress, 1147 + int end_progress, 1148 + Secure_Channel channel, Buffer wrapped_challenge, 1149 + const char tokenType, 1150 + const char keyType, 1151 + Buffer key_check, 1152 + Buffer plaintext_challenge, 1153 + const char cuid, 1154 + const char msn, 1155 + const char khex, 1156 + TokenKeyType key_type, 1157 + const char profileId, 1158 + const char userid, 1159 + const char cert_id, 1160 + const char publisher_id, 1161 + const char cert_attr_id, 1162 + const char pri_attr_id, 1163 + const char pub_attr_id, 1164 + BYTE se_p1, BYTE se_p2, BYTE algorithm, int keysize, const char connid, const char keyTypePrefix,char * applet_version); 1165 1166 bool DoRenewal(const char connid, 1167 const char profileId, 1168 Index: tps/src/include/cms/CertEnroll.h 1169 =================================================================== 1170 --- tps/src/include/cms/CertEnroll.h (revision 2471) 1171 +++ tps/src/include/cms/CertEnroll.h (working copy) 1172 @@ -55,8 +55,9 @@ 1173 TOKENDB_PUBLIC CertEnroll(); 1174 TOKENDB_PUBLIC ~CertEnroll(); 1175 1176 + 1177 SECKEYPublicKey ParsePublicKeyBlob(unsigned char * /blob/, 1178 - Buffer * /challenge/); 1179 + Buffer * /challenge/, bool isECC); 1180 Buffer EnrollCertificate(SECKEYPublicKey * /pk_parsed/, 1181 const char profileId, 1182 const char * /uid/, 1183 @@ -64,12 +65,15 @@ 1184 char error_msg, 1185 SECItem encodedPublicKeyInfo = NULL); 1186 ReturnStatus verifyProof(SECKEYPublicKey /pk/, SECItem /siProof/, 1187 - unsigned short /pkeyb_len/, unsigned char /pkeyb/, 1188 - Buffer /challenge/); 1189 + unsigned short /pkeyb_len/, unsigned char /pkeyb/, 1190 + Buffer /challenge/, bool /isECC/); 1191 TOKENDB_PUBLIC Buffer RenewCertificate(PRUint64 serialno, const char connid, const char profileId, char error_msg); 1192 TOKENDB_PUBLIC int RevokeCertificate(const char reason, const char serialno, const char connid, char &status); 1193 TOKENDB_PUBLIC int UnrevokeCertificate(const char serialno, const char connid, char &status); 1194 PSHttpResponse * sendReqToCA(const char servlet, const char parameters, const char connid); 1195 Buffer * parseResponse(PSHttpResponse * /resp/); 1196 + 1197 + SECKEYECParams * encode_ec_params(char curve); 1198 + 1199 }; 1200 #endif / CERTENROLL_H / 1201 Index: tps/src/include/main/Buffer.h 1202 =================================================================== 1203 --- tps/src/include/main/Buffer.h (revision 2471) 1204 +++ tps/src/include/main/Buffer.h (working copy) 1205 @@ -167,6 +167,9 @@ 1206 / 1207 TPS_PUBLIC void replace(unsigned int i, const BYTE cpy, unsigned int n); 1208 1209 + TPS_PUBLIC unsigned char getBuf(); 1210 + TPS_PUBLIC unsigned int getLen(); 1211 + 1212 / 1213 * returns a hex version of the buffer 1214 / 1215 Index: tps/src/include/engine/RA.h 1216 =================================================================== 1217 --- tps/src/include/engine/RA.h (revision 2471) 1218 +++ tps/src/include/engine/RA.h (working copy) 1219 @@ -79,6 +79,13 @@ 1220 LL_ALL_DATA_IN_PDU = 9 1221 }; 1222 1223 +enum RA_Algs { 1224 + ALG_RSA = 1, 1225 + ALG_RSA_CRT = 2, 1226 + ALG_DSA = 3, 1227 + ALG_EC_F2M = 4, 1228 + ALG_EC_FP = 5 1229 +}; 1230 1231 #ifdef XP_WIN32 1232 #define TPS_PUBLIC __declspec(dllexport) 1233 @@ -124,12 +131,12 @@ 1234 char kek_kekSessionKey_s, 1235 char keycheck_s, 1236 const char connId); 1237 - static void ServerSideKeyGen(RA_Session session, const char cuid, 1238 + static void ServerSideKeyGen(RA_Session session, const char cuid, 1239 const char userid, char kekSessionKey_s, 1240 - char publickey_s, 1241 + char publickey_s, 1242 char wrappedPrivateKey_s, 1243 char ivParam_s, const char connId, 1244 - bool archive, int keysize); 1245 + bool archive, int keysize, bool isECC); 1246 static void RecoverKey(RA_Session session, const char cuid, 1247 const char userid, char kekSessionKey_s, 1248 char cert_s, char publickey_s, 1249 @@ -363,6 +370,7 @@ 1250 static void CleanupPublishers(); 1251 static int Failover(HttpConnection &conn, int len); 1252 1253 + static bool isAlgorithmECC(BYTE algorithm); 1254 TPS_PUBLIC static SECCertificateUsage getCertificateUsage(const char certusage); 1255 TPS_PUBLIC static bool verifySystemCertByNickname(const char nickname, const char certUsage); 1256 TPS_PUBLIC static bool verifySystemCerts(); 1257 Index: tps/src/include/channel/Secure_Channel.h 1258 =================================================================== 1259 --- tps/src/include/channel/Secure_Channel.h (revision 2471) 1260 +++ tps/src/include/channel/Secure_Channel.h (working copy) 1261 @@ -125,10 +125,18 @@ 1262 int CreatePKCS11CertAttrs(TokenKeyType type, const char id, const char label, Buffer keyid); 1263 Buffer CreatePKCS11PriKeyAttrsBuffer(TokenKeyType type, const char id, const char label, Buffer keyid, 1264 Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix); 1265 + 1266 + Buffer CreatePKCS11ECCPriKeyAttrsBuffer(TokenKeyType type, const char id, const char label, Buffer keyid, 1267 + SECKEYECParams ecParams, const char opType, const char tokenType, const char keyTypePrefix); 1268 + 1269 int CreatePKCS11PriKeyAttrs(TokenKeyType type, const char id, const char label, Buffer keyid, 1270 Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix); 1271 Buffer CreatePKCS11PubKeyAttrsBuffer(TokenKeyType type, const char id, const char label, Buffer keyid, 1272 Buffer exponent, Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix); 1273 + 1274 + Buffer CreatePKCS11ECCPubKeyAttrsBuffer(TokenKeyType key_type, const char id, const char label, Buffer keyid, SECKEYECPublicKey publicKey, 1275 + SECKEYECParams ecParams, const char opType, const char tokenType, const char keyTypePrefix); 1276 + 1277 int CreatePKCS11PubKeyAttrs(TokenKeyType type, const char id, const char label, Buffer keyid, 1278 Buffer exponent, Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix); 1279 APDU_Response SendTokenAPU(APDU apdu); 1280 Index: tps/src/main/Buffer.cpp 1281 =================================================================== 1282 --- tps/src/main/Buffer.cpp (revision 2471) 1283 +++ tps/src/main/Buffer.cpp (working copy) 1284 @@ -222,6 +222,16 @@ 1285 return s; 1286 } 1287 1288 +TPS_PUBLIC unsigned char 1289 +Buffer::getBuf() { 1290 + return (unsigned char ) buf; 1291 +} 1292 + 1293 +TPS_PUBLIC unsigned int 1294 +Buffer::getLen() { 1295 + return len; 1296 +} 1297 + 1298 TPS_PUBLIC char * 1299 Buffer::toHex() 1300 { 1301 Index: tps/src/main/ObjectSpec.cpp 1302 =================================================================== 1303 --- tps/src/main/ObjectSpec.cpp (revision 2471) 1304 +++ tps/src/main/ObjectSpec.cpp (working copy) 1305 @@ -190,6 +190,7 @@ 1306 case CKA_KEY_TYPE: 1307 type = DATATYPE_INTEGER; 1308 data = b->substr(curpos+6, 4); 1309 + found = 1; 1310 / build by PKCS11 / 1311 break; 1312 case CKA_CLASS: 1313 @@ -208,6 +209,18 @@ 1314 data = b->substr(curpos+6, 4); 1315 / build by PKCS11 / 1316 break; 1317 + 1318 + case CKA_EC_PARAMS: 1319 + type = DATATYPE_STRING; 1320 + data = b->substr(curpos+6, attribute_size); 1321 + found = 1; 1322 + break; 1323 + 1324 + case CKA_EC_POINT: 1325 + type = DATATYPE_STRING; 1326 + data = b->substr(curpos+6, attribute_size); 1327 + found = 1; 1328 + break; 1329 default: 1330 RA::Debug("ObjectSpec::ParseKeyBlob", 1331 "skipped attribute_id = %lx", 1332 Index: tps/src/engine/RA.cpp 1333 =================================================================== 1334 --- tps/src/engine/RA.cpp (revision 2471) 1335 +++ tps/src/engine/RA.cpp (working copy) 1336 @@ -1287,7 +1287,7 @@ 1337 char publicKey_s, 1338 char wrappedPrivateKey_s, 1339 char ivParam_s, const char connId, 1340 - bool archive, int keysize) 1341 + bool archive, int keysize, bool isECC) 1342 { 1343 1344 const char FN="RA::ServerSideKeyGen"; 1345 @@ -1357,8 +1357,26 @@ 1346 RA::Debug(LL_PER_CONNECTION, FN, 1347 "wrappedDESKey_s=%s", wrappedDESKey_s); 1348 1349 - PR_snprintf((char )body, MAX_BODY_LEN, 1350 - "archive=%s&CUID=%s&userid=%s&keysize=%d&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, keysize, wrappedDESKey_s); 1351 + if (isECC) { 1352 + char eckeycurve = NULL; 1353 + if (keysize == 521) { 1354 + eckeycurve = "nistp521"; 1355 + } else if (keysize == 384) { 1356 + eckeycurve = "nistp384"; 1357 + } else if (keysize == 256) { 1358 + eckeycurve = "nistp256"; 1359 + } else { 1360 + RA::Debug(LL_PER_CONNECTION, FN, 1361 + "unrecognized ECC keysize %d, setting to nistp256", keysize); 1362 + keysize = 256; 1363 + eckeycurve = "nistp256"; 1364 + } 1365 + PR_snprintf((char )body, MAX_BODY_LEN, 1366 + "archive=%s&CUID=%s&userid=%s&keytype=EC&eckeycurve=%s&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, eckeycurve, wrappedDESKey_s); 1367 + } else { 1368 + PR_snprintf((char )body, MAX_BODY_LEN, 1369 + "archive=%s&CUID=%s&userid=%s&keysize=%d&keytype=RSA&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, keysize, wrappedDESKey_s); 1370 + } 1371 RA::Debug(LL_PER_CONNECTION, FN, 1372 "sending to DRM: query=%s", body); 1373 1374 @@ -3612,3 +3630,15 @@ 1375 return newKey; 1376 } 1377 1378 +bool RA::isAlgorithmECC(BYTE alg) 1379 +{ 1380 + bool result = false; 1381 + 1382 + if (alg == ALG_EC_F2M || alg == ALG_EC_FP) 1383 + result = true; 1384 + 1385 + RA::Debug(LL_PER_SERVER, "RA::isAlgorithmECC", " alg: %d result: %d", alg, result); 1386 + 1387 + return result; 1388 +} 1389 + 1390 Index: tps/src/channel/Secure_Channel.cpp 1391 =================================================================== 1392 --- tps/src/channel/Secure_Channel.cpp (revision 2471) 1393 +++ tps/src/channel/Secure_Channel.cpp (working copy) 1394 @@ -38,6 +38,7 @@ 1395 #include "apdu/Read_Object_APDU.h" 1396 #include "apdu/Write_Object_APDU.h" 1397 #include "apdu/Generate_Key_APDU.h" 1398 +#include "apdu/Generate_Key_ECC_APDU.h" 1399 #include "apdu/Put_Key_APDU.h" 1400 #include "apdu/Delete_File_APDU.h" 1401 #include "apdu/Load_File_APDU.h" 1402 @@ -142,6 +143,7 @@ 1403 } 1404 } 1405 1406 + RA::Debug(LL_PER_PDU,"Secure_Channel::ComputeAPDU","Completed apdu."); 1407 rc = 1; 1408 loser: 1409 if( mac != NULL ) { 1410 @@ -180,6 +182,8 @@ 1411 apdu->SetMAC(mac); 1412 m_icv = mac; 1413 1414 + RA::DebugBuffer("Secure_Channel::ComputeAPDUMac ", "mac", 1415 + mac); 1416 return mac; 1417 } / EncodeAPDUMac / 1418 1419 @@ -1340,6 +1344,8 @@ 1420 { 1421 int rc = -1; 1422 Generate_Key_APDU generate_key_apdu = NULL; 1423 + Generate_Key_ECC_APDU generate_key_ecc_apdu = NULL; 1424 + 1425 APDU_Response response = NULL; 1426 RA_Token_PDU_Request_Msg token_pdu_request_msg = NULL; 1427 RA_Token_PDU_Response_Msg token_pdu_response_msg = NULL; 1428 @@ -1348,9 +1354,19 @@ 1429 1430 RA::Debug("Secure_Channel::GenerateKey", 1431 "Secure_Channel::GenerateKey"); 1432 - generate_key_apdu = new Generate_Key_APDU(p1, p2, alg, keysize, option, 1433 - alg, wrapped_challenge, key_check); 1434 - rc = ComputeAPDU(generate_key_apdu); 1435 + 1436 + bool isECC = RA::isAlgorithmECC(alg); 1437 + 1438 + if (isECC) { 1439 + generate_key_ecc_apdu = new Generate_Key_ECC_APDU(p1, p2, alg, keysize, option, 1440 + alg, wrapped_challenge, key_check); 1441 + rc = ComputeAPDU(generate_key_ecc_apdu); 1442 + } else { 1443 + generate_key_apdu = new Generate_Key_APDU(p1, p2, alg, keysize, option, 1444 + alg, wrapped_challenge, key_check); 1445 + rc = ComputeAPDU(generate_key_apdu); 1446 + } 1447 + 1448 if (rc == -1) 1449 goto loser; 1450 1451 @@ -1358,8 +1374,15 @@ 1452 mac = ComputeAPDUMac(generate_key_apdu); 1453 generate_key_apdu->SetMAC(mac); 1454 / 1455 - token_pdu_request_msg = new RA_Token_PDU_Request_Msg( 1456 - generate_key_apdu); 1457 + 1458 + if (generate_key_ecc_apdu != NULL ) { 1459 + token_pdu_request_msg = new RA_Token_PDU_Request_Msg( 1460 + generate_key_ecc_apdu); 1461 + } else { 1462 + token_pdu_request_msg = new RA_Token_PDU_Request_Msg( 1463 + generate_key_apdu); 1464 + } 1465 + 1466 m_session->WriteMsg(token_pdu_request_msg); 1467 RA::Debug("Secure_Channel::GenerateKey", 1468 "Sent token_pdu_request_msg"); 1469 @@ -2177,9 +2200,9 @@ 1470 Buffer b(256); // allocate some space 1471 b.resize(7); // this keeps the allocated space around 1472 1473 - RA::Debug("Secure_Channel::CreatePKCS11CertAttrs", "id=%s", id); 1474 - RA::Debug("Secure_Channel::CreatePKCS11CertAttrs", "label=%s", label); 1475 - RA::DebugBuffer("Secure_Channel::CreatePKCS11CertAttrs", "keyid", keyid); 1476 + RA::Debug("Secure_Channel::CreatePKCS11CertAttrsBuffer", "id=%s", id); 1477 + RA::Debug("Secure_Channel::CreatePKCS11CertAttrsBuffer", "label=%s", label); 1478 + RA::DebugBuffer("Secure_Channel::CreatePKCS11CertAttrsBuffer", "keyid", keyid); 1479 AppendAttribute(b, CKA_LABEL, strlen(label), (BYTE)label); 1480 // hash of pubk 1481 AppendAttribute(b, CKA_ID, keyid->size(), (BYTE)keyid); 1482 @@ -2301,6 +2324,7 @@ 1483 M 00020001010000000100010100000100 1484 M 00040000000000000000000403000000 1485 / 1486 + 1487 Buffer Secure_Channel::CreatePKCS11PriKeyAttrsBuffer(TokenKeyType key_type, const char id, const char label, Buffer keyid, 1488 Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix) 1489 { 1490 @@ -2383,6 +2407,39 @@ 1491 1492 } / CreatePKCS11PriKeyAttrs / 1493 1494 +Buffer Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer(TokenKeyType type, const char id, const char label, Buffer keyid, 1495 + SECKEYECParams ecParams, const char opType, const char tokenType, const char keyTypePrefix) 1496 +{ 1497 + 1498 + BYTE keytype[8] = { 3,0,0,0 }; 1499 + BYTE p11class[4] = { 3,0,0,0 }; 1500 + 1501 + Buffer b(256); // allocate some space 1502 + b.resize(7); // this keeps the allocated space around 1503 + 1504 + if (label != NULL) 1505 + RA::Debug("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "label=%s", label); 1506 + if (keyid != NULL) 1507 + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "keyid", keyid); 1508 + if (id != NULL) 1509 + RA::Debug("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "id=%s",id); 1510 + 1511 + AppendAttribute(b,CKA_KEY_TYPE, 4, keytype); 1512 + AppendAttribute(b,CKA_CLASS, 4, p11class ); 1513 + // hash of pubk 1514 + AppendAttribute(b,CKA_ID, keyid->size(), (BYTE)keyid); 1515 + 1516 + AppendAttribute(b,CKA_EC_PARAMS, ecParams->len, ecParams->data); 1517 + AppendKeyCapabilities(b, opType, tokenType, keyTypePrefix, "private"); 1518 + 1519 + FinalizeBuffer(b, id); 1520 + 1521 + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPriKeyAttrsBuffer", "buffer", &b); 1522 + 1523 + return b; 1524 + 1525 +} 1526 + 1527 / 1528 Public Key: (k1) 1529 CKA_PUBLIC_EXPONENT(0x0122) 1530 @@ -2461,6 +2518,43 @@ 1531 return b; 1532 } / CreatePKCS11PubKeyAttrs / 1533 1534 + 1535 +Buffer Secure_Channel::CreatePKCS11ECCPubKeyAttrsBuffer(TokenKeyType key_type, const char id, const char label, Buffer keyid, 1536 + SECKEYECPublicKey publicKey, SECKEYECParams ecParams, const char opType, const char tokenType, const char keyTypePrefix) 1537 +{ 1538 + BYTE p11class[4] = { 2,0,0,0 }; 1539 + // BYTE ZERO[1] = { 0 }; 1540 + // BYTE ONE[1] = { 1 }; 1541 + // char configname[256]; 1542 + 1543 + BYTE keytype[4] = { 3,0,0,0 }; 1544 + Buffer b(256); // allocate some space 1545 + b.resize(7); // this keeps the allocated space around 1546 + 1547 + if (label != NULL) 1548 + RA::Debug("Secure_Channel::CreatePKCS11ECCPubAttrsBuffer", "label=%s", label); 1549 + if (keyid != NULL) 1550 + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPubAttrsBuffer", "keyid", keyid); 1551 + 1552 + // XXX TUES 1553 + // hash of pubk 1554 + AppendAttribute(b,CKA_ID, keyid->size(), (BYTE)keyid); 1555 + AppendAttribute(b, CKA_CLASS, 4, p11class ); // type of object 1556 + AppendAttribute(b,CKA_KEY_TYPE, 4, keytype); // CKK_EC key type 1557 + AppendAttribute(b,CKA_EC_PARAMS, ecParams->len, (BYTE ) ecParams->data); 1558 + AppendAttribute(b, CKA_EC_POINT, publicKey->publicValue.len, (BYTE ) publicKey->publicValue.data); 1559 + 1560 + AppendKeyCapabilities(b, opType, tokenType, keyTypePrefix, "public"); 1561 + 1562 + FinalizeBuffer(b, id); 1563 + 1564 + RA::DebugBuffer("Secure_Channel::CreatePKCS11ECCPubAttrsBuffer", "buffer", &b); 1565 + 1566 + return b; 1567 +} / CreatePKCS11ECCPubKeyAttrs / 1568 + 1569 + 1570 + 1571 int Secure_Channel::CreatePKCS11PubKeyAttrs(TokenKeyType key_type, const char id, const char label, Buffer keyid, 1572 Buffer exponent, Buffer modulus, const char opType, const char tokenType, const char keyTypePrefix) 1573 { 1574 Index: kra/src/com/netscape/kra/NetkeyKeygenService.java 1575 =================================================================== 1576 --- kra/src/com/netscape/kra/NetkeyKeygenService.java (revision 2471) 1577 +++ kra/src/com/netscape/kra/NetkeyKeygenService.java (working copy) 1578 @@ -62,7 +62,10 @@ 1579 import com.netscape.certsrv.authentication.; 1580 import com.netscape.certsrv.apps.; 1581 import com.netscape.certsrv.apps.CMS; 1582 +import com.netscape.cmsutil.crypto.CryptoUtil; 1583 +import com.netscape.cms.servlet.key.KeyRecordParser; 1584 1585 + 1586 //for b64 encoding 1587 import org.mozilla.jss.util.Base64OutputStream; 1588 import java.io.ByteArrayOutputStream; 1589 @@ -146,7 +149,7 @@ 1590 } 1591 1592 public KeyPair generateKeyPair( 1593 - KeyPairAlgorithm kpAlg, int keySize, PQGParams pqg) 1594 + KeyPairAlgorithm kpAlg, int keySize, String keyCurve, PQGParams pqg) 1595 throws NoSuchAlgorithmException, TokenException, InvalidAlgorithmParameterException, 1596 InvalidParameterException, PQGParamGenException { 1597 1598 @@ -165,20 +168,28 @@ 1599 sensitive == true 1600 extractable == true 1601 / 1602 + 1603 KeyPairGenerator kpGen = token.getKeyPairGenerator(kpAlg); 1604 IConfigStore config = CMS.getConfigStore(); 1605 IConfigStore kgConfig = config.getSubStore("kra.keygen"); 1606 boolean tp = false; 1607 boolean sp = false; 1608 boolean ep = false; 1609 - if (kgConfig != null) { 1610 + if ((kgConfig != null) && (!kgConfig.equals(""))) { 1611 try { 1612 tp = kgConfig.getBoolean("temporaryPairs", false); 1613 sp = kgConfig.getBoolean("sensitivePairs", false); 1614 ep = kgConfig.getBoolean("extractablePairs", false); 1615 + CMS.debug("NetkeyKeygenService: found config store: kra.keygen"); 1616 // by default, let nethsm work 1617 if ((tp == false) && (sp == false) && (ep == false)) { 1618 - tp = true; 1619 + if (kpAlg == KeyPairAlgorithm.EC) { 1620 + // set to what works for nethsm 1621 + tp = true; 1622 + sp = false; 1623 + ep = true; 1624 + } else 1625 + tp = true; 1626 } 1627 } catch (Exception e) { 1628 CMS.debug("NetkeyKeygenService: kgConfig.getBoolean failed"); 1629 @@ -188,70 +199,111 @@ 1630 } else { 1631 // by default, let nethsm work 1632 CMS.debug("NetkeyKeygenService: cannot find config store: kra.keygen, assume temporaryPairs==true"); 1633 - tp = true; 1634 + if (kpAlg == KeyPairAlgorithm.EC) { 1635 + // set to what works for nethsm 1636 + tp = true; 1637 + sp = false; 1638 + ep = true; 1639 + } else { 1640 + tp = true; 1641 + } 1642 } 1643 - / only specified to "true" will it be set / 1644 - if (tp == true) { 1645 - CMS.debug("NetkeyKeygenService: setting temporaryPairs to true"); 1646 - kpGen.temporaryPairs(true); 1647 - } 1648 - if (sp == true) { 1649 - CMS.debug("NetkeyKeygenService: setting sensitivePairs to true"); 1650 - kpGen.sensitivePairs(true); 1651 - } 1652 - if (ep == true) { 1653 - CMS.debug("NetkeyKeygenService: setting extractablePairs to true"); 1654 - kpGen.extractablePairs(true); 1655 - } 1656 + 1657 + if (kpAlg == KeyPairAlgorithm.EC) { 1658 + 1659 + boolean isECDHE = false; 1660 + KeyPair pair = null; 1661 + 1662 + // used with isECDHE == true 1663 + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask_ECDSA[] = { 1664 + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.DERIVE 1665 + }; 1666 + 1667 + // used with isECDHE == false 1668 + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask_ECDH[] = { 1669 + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN, 1670 + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN_RECOVER 1671 + }; 1672 + 1673 + try { 1674 + pair = CryptoUtil.generateECCKeyPair(token.getName(), /ECC_curve default/ keyCurve , 1675 + null, 1676 + (isECDHE==true) ? usages_mask_ECDSA: usages_mask_ECDH, 1677 + tp /temporary/, sp? 1:0 /sensitive/, ep? 1:0 /extractable/); 1678 + CMS.debug("NetkeyKeygenService: after key pair generation" ); 1679 + } catch (Exception e) { 1680 + CMS.debug("NetkeyKeygenService: key pair generation with exception:"+e.toString()); 1681 + } 1682 + return pair; 1683 + 1684 + } else { // !EC 1685 + //only specified to "true" will it be set 1686 + if (tp == true) { 1687 + CMS.debug("NetkeyKeygenService: setting temporaryPairs to true"); 1688 + kpGen.temporaryPairs(true); 1689 + } 1690 + 1691 + if (sp == true) { 1692 + CMS.debug("NetkeyKeygenService: setting sensitivePairs to true"); 1693 + kpGen.sensitivePairs(true); 1694 + } 1695 + 1696 + if (ep == true) { 1697 + CMS.debug("NetkeyKeygenService: setting extractablePairs to true"); 1698 + kpGen.extractablePairs(true); 1699 + } 1700 1701 - if (kpAlg == KeyPairAlgorithm.DSA) { 1702 - if (pqg == null) { 1703 + if (kpAlg == KeyPairAlgorithm.DSA) { 1704 + if (pqg == null) { 1705 + kpGen.initialize(keySize); 1706 + } else { 1707 + kpGen.initialize(pqg); 1708 + } 1709 + } else { 1710 kpGen.initialize(keySize); 1711 - } else { 1712 - kpGen.initialize(pqg); 1713 } 1714 - } else { 1715 - kpGen.initialize(keySize); 1716 - } 1717 1718 - if (pqg == null) { 1719 - KeyPair kp = null; 1720 - synchronized (new Object()) { 1721 - CMS.debug("NetkeyKeygenService: key pair generation begins"); 1722 - kp = kpGen.genKeyPair(); 1723 - CMS.debug("NetkeyKeygenService: key pair generation done"); 1724 - mKRA.addEntropy(true); 1725 - } 1726 - return kp; 1727 - } else { 1728 - // DSA 1729 - KeyPair kp = null; 1730 + if (pqg == null) { 1731 + KeyPair kp = null; 1732 + synchronized (new Object()) { 1733 + CMS.debug("NetkeyKeygenService: key pair generation begins"); 1734 + kp = kpGen.genKeyPair(); 1735 + CMS.debug("NetkeyKeygenService: key pair generation done"); 1736 + mKRA.addEntropy(true); 1737 + } 1738 + return kp; 1739 + } else { 1740 + // DSA 1741 + KeyPair kp = null; 1742 1743 - / no DSA for now... netkey prototype 1744 - do { 1745 - // 602548 NSS bug - to overcome it, we use isBadDSAKeyPair 1746 - kp = kpGen.genKeyPair(); 1747 + / no DSA for now... netkey prototype 1748 + do { 1749 + // 602548 NSS bug - to overcome it, we use isBadDSAKeyPair 1750 + kp = kpGen.genKeyPair(); 1751 + } 1752 + while (isBadDSAKeyPair(kp)); 1753 + / 1754 + return kp; 1755 } 1756 - while (isBadDSAKeyPair(kp)); 1757 - / 1758 - return kp; 1759 } 1760 } 1761 1762 1763 1764 public KeyPair generateKeyPair( String alg, 1765 - int keySize, PQGParams pqg) throws EBaseException { 1766 + int keySize, String keyCurve, PQGParams pqg) throws EBaseException { 1767 1768 KeyPairAlgorithm kpAlg = null; 1769 1770 if (alg.equals("RSA")) 1771 kpAlg = KeyPairAlgorithm.RSA; 1772 + else if (alg.equals("EC")) 1773 + kpAlg = KeyPairAlgorithm.EC; 1774 else 1775 kpAlg = KeyPairAlgorithm.DSA; 1776 1777 try { 1778 - KeyPair kp = generateKeyPair( kpAlg, keySize, pqg); 1779 + KeyPair kp = generateKeyPair( kpAlg, keySize, keyCurve, pqg); 1780 1781 return kp; 1782 } catch (InvalidParameterException e) { 1783 @@ -324,7 +376,7 @@ 1784 byte[] wrapped_des_key; 1785 1786 byte iv[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}; 1787 - String iv_s =""; 1788 + String iv_s =""; 1789 try { 1790 SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); 1791 random.nextBytes(iv); 1792 @@ -332,34 +384,35 @@ 1793 CMS.debug("NetkeyKeygenService.serviceRequest: "+ e.toString()); 1794 } 1795 1796 - IVParameterSpec algParam = new IVParameterSpec(iv); 1797 + IVParameterSpec algParam = new IVParameterSpec(iv); 1798 1799 wrapped_des_key = null; 1800 - boolean archive = true; 1801 - PK11SymKey sk= null; 1802 - byte[] publicKeyData = null;; 1803 - String PubKey = ""; 1804 + boolean archive = true; 1805 + PK11SymKey sk= null; 1806 + byte[] publicKeyData = null;; 1807 + String PubKey = ""; 1808 1809 String id = request.getRequestId().toString(); 1810 if (id != null) { 1811 auditArchiveID = id.trim(); 1812 } 1813 1814 - String rArchive = request.getExtDataInString(IRequest.NETKEY_ATTR_ARCHIVE_FLAG); 1815 - if (rArchive.equals("true")) { 1816 - archive = true; 1817 + String rArchive = request.getExtDataInString(IRequest.NETKEY_ATTR_ARCHIVE_FLAG); 1818 + if (rArchive.equals("true")) { 1819 + archive = true; 1820 CMS.debug("NetkeyKeygenService: serviceRequest " +"archival requested for serverSideKeyGen"); 1821 - } else { 1822 - archive = false; 1823 + } else { 1824 + archive = false; 1825 CMS.debug("NetkeyKeygenService: serviceRequest " +"archival not requested for serverSideKeyGen"); 1826 } 1827 1828 String rCUID = request.getExtDataInString(IRequest.NETKEY_ATTR_CUID); 1829 String rUserid = request.getExtDataInString(IRequest.NETKEY_ATTR_USERID); 1830 - String rKeysize = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_SIZE); 1831 - int keysize = Integer.parseInt(rKeysize); 1832 - auditSubjectID=rCUID+":"+rUserid; 1833 1834 + String rKeytype = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_TYPE); 1835 + 1836 + auditSubjectID=rCUID+":"+rUserid; 1837 + 1838 SessionContext sContext = SessionContext.getContext(); 1839 String agentId=""; 1840 if (sContext != null) { 1841 @@ -381,15 +434,41 @@ 1842 wrapped_des_key = com.netscape.cmsutil.util.Utils.SpecialDecode(rWrappedDesKeyString); 1843 CMS.debug("NetkeyKeygenService: wrapped_des_key specialDecoded"); 1844 1845 - // get the token for generating user keys 1846 - CryptoToken keygenToken = mKRA.getKeygenToken(); 1847 - if (keygenToken == null) { 1848 - CMS.debug("NetkeyKeygenService: failed getting keygenToken"); 1849 - request.setExtData(IRequest.RESULT, Integer.valueOf(10)); 1850 - return false; 1851 - } else 1852 - CMS.debug("NetkeyKeygenService: got keygenToken"); 1853 +/ 1854 + if ((rKeytype == null) || (rKeytype.equals(""))) { 1855 + rKeytype = "RSA"; 1856 + } 1857 +/ 1858 1859 + if ((rKeytype == null) || (rKeytype.equals(""))) { 1860 + CMS.debug("NetkeyKeygenService: serviceRequest: key type is null"); 1861 + rKeytype = "RSA"; 1862 + } else 1863 + CMS.debug("NetkeyKeygenService: serviceRequest: key type = "+ rKeytype); 1864 + 1865 + / for EC, keysize is ignored, only key curve is used / 1866 + String rKeysize = "2048"; 1867 + int keysize = 2048; 1868 + String rKeycurve = "nistp256"; 1869 + if (rKeytype.equals("EC")) { 1870 + rKeycurve = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_EC_CURVE); 1871 + if ((rKeycurve == null) || (rKeycurve.equals(""))) { 1872 + rKeycurve = "nistp256"; 1873 + } 1874 + } else { 1875 + rKeysize = request.getExtDataInString(IRequest.NETKEY_ATTR_KEY_SIZE); 1876 + keysize = Integer.parseInt(rKeysize); 1877 + } 1878 + 1879 + // get the token for generating user keys 1880 + CryptoToken keygenToken = mKRA.getKeygenToken(); 1881 + if (keygenToken == null) { 1882 + CMS.debug("NetkeyKeygenService: failed getting keygenToken"); 1883 + request.setExtData(IRequest.RESULT, Integer.valueOf(10)); 1884 + return false; 1885 + } else 1886 + CMS.debug("NetkeyKeygenService: got keygenToken"); 1887 + 1888 if ((wrapped_des_key != null) && 1889 (wrapped_des_key.length > 0)) { 1890 1891 @@ -401,8 +480,10 @@ 1892 1893 CMS.debug("NetkeyKeygenService: about to generate key pair"); 1894 1895 - keypair = generateKeyPair("RSA"/alg/, 1896 - keysize /Integer.parseInt(len)/, null /pqgParams/); 1897 + keypair = generateKeyPair(rKeytype / rKeytype: "RSA" or "EC" /, 1898 + keysize /Integer.parseInt(len)/, 1899 + rKeycurve / for "EC" only /, 1900 + null /pqgParams/); 1901 1902 if (keypair == null) { 1903 CMS.debug("NetkeyKeygenService: failed generating key pair for "+rCUID+":"+rUserid); 1904 @@ -421,18 +502,20 @@ 1905 CMS.debug("NetkeyKeygenService: finished generate key pair for " +rCUID+":"+rUserid); 1906 1907 try { 1908 - publicKeyData = keypair.getPublic().getEncoded(); 1909 - if (publicKeyData == null) { 1910 - request.setExtData(IRequest.RESULT, Integer.valueOf(4)); 1911 - CMS.debug("NetkeyKeygenService: failed getting publickey encoded"); 1912 - return false; 1913 - } else { 1914 - //CMS.debug("NetkeyKeygenService: public key binary length ="+ publicKeyData.length); 1915 - PubKey = base64Encode(publicKeyData); 1916 + publicKeyData = keypair.getPublic().getEncoded(); 1917 + if (publicKeyData == null) { 1918 + request.setExtData(IRequest.RESULT, Integer.valueOf(4)); 1919 + CMS.debug("NetkeyKeygenService: failed getting publickey encoded"); 1920 + return false; 1921 + } else { 1922 + //CMS.debug("NetkeyKeygenService: public key binary length ="+ publicKeyData.length); 1923 + / url encode / 1924 + PubKey = com.netscape.cmsutil.util.Utils.SpecialEncode(publicKeyData); 1925 + CMS.debug("NetkeyKeygenService: EC PubKey special encoded"); 1926 1927 - //CMS.debug("NetkeyKeygenService: public key length =" + PubKey.length()); 1928 - request.setExtData("public_key", PubKey); 1929 - } 1930 + //CMS.debug("NetkeyKeygenService: public key length =" + PubKey.length()); 1931 + request.setExtData("public_key", PubKey); 1932 + } 1933 1934 auditMessage = CMS.getLogMessage( 1935 LOGGING_SIGNED_AUDIT_SERVER_SIDE_KEYGEN_REQUEST_PROCESSED_SUCCESS, 1936 @@ -558,18 +641,52 @@ 1937 CMS.debug("NetkeyKeygenService: privatekey recording failed"); 1938 return false; 1939 } else 1940 - CMS.debug("NetkeyKeygenService: got key record"); 1941 + CMS.debug("NetkeyKeygenService: got key record"); 1942 1943 - // we deal with RSA key only 1944 - try { 1945 - RSAPublicKey rsaPublicKey = new RSAPublicKey(publicKeyData); 1946 + if (rKeytype.equals("RSA")) { 1947 + try { 1948 + RSAPublicKey rsaPublicKey = new RSAPublicKey(publicKeyData); 1949 1950 - rec.setKeySize(Integer.valueOf(rsaPublicKey.getKeySize())); 1951 - } catch (InvalidKeyException e) { 1952 - request.setExtData(IRequest.RESULT, Integer.valueOf(11)); 1953 - CMS.debug("NetkeyKeygenService: failed:InvalidKeyException"); 1954 - return false; 1955 - } 1956 + rec.setKeySize(Integer.valueOf(rsaPublicKey.getKeySize())); 1957 + } catch (InvalidKeyException e) { 1958 + request.setExtData(IRequest.RESULT, Integer.valueOf(11)); 1959 + CMS.debug("NetkeyKeygenService: failed:InvalidKeyException"); 1960 + return false; 1961 + } 1962 + } else if (rKeytype.equals("EC")) { 1963 + CMS.debug("NetkeyKeygenService: alg is EC"); 1964 + String oidDescription = "UNDETERMINED"; 1965 + // for KeyRecordParser 1966 + MetaInfo metaInfo = new MetaInfo(); 1967 + 1968 + try { 1969 + byte curve[] = 1970 + ASN1Util.getECCurveBytesByX509PublicKeyBytes(publicKeyData, 1971 + false / without tag and size /); 1972 + if (curve.length != 0) { 1973 + oidDescription = ASN1Util.getOIDdescription(curve); 1974 + } else { 1975 + / this is to be used by derdump / 1976 + byte curveTS[] = 1977 + ASN1Util.getECCurveBytesByX509PublicKeyBytes(publicKeyData, 1978 + true / with tag and size */); 1979 + if (curveTS.length != 0) { 1980 + oidDescription = CMS.BtoA(curveTS); 1981 + } 1982 + } 1983 + } catch (Exception e) { 1984 + CMS.debug("NetkeyKeygenService: ASN1Util.getECCurveBytesByX509PublicKeyByte() throws exception: "+ e.toString()); 1985 + CMS.debug("NetkeyKeygenService: exception allowed. continue"); 1986 + } 1987 + 1988 + metaInfo.set(KeyRecordParser.OUT_KEY_EC_CURVE, 1989 + oidDescription); 1990 + 1991 + rec.set(IKeyRecord.ATTR_META_INFO, metaInfo); 1992 + // key size does not apply to EC; 1993 + rec.setKeySize(-1); 1994 + } 1995 + 1996 //?? 1997 IKeyRepository storage = mKRA.getKeyRepository(); 1998 BigInteger serialNo = storage.getNextSerialNumber();
Dogtag PKI is moving from Pagure issues to GitHub issues. This means that existing or new issues will be reported and tracked through Dogtag PKI's GitHub Issue tracker.
This issue has been cloned to GitHub and is available here: https://github.com/dogtagpki/pki/issues/875
If you want to receive further updates on the issue, please navigate to the GitHub issue and click on Subscribe button.
Subscribe
Thank you for understanding, and we apologize for any inconvenience.