From e6895613ea1c116003166e456fdca3ac86dfaeec Mon Sep 17 00:00:00 2001 From: Christina Fu Date: Tue, 18 Sep 2012 14:51:06 -0700 Subject: https://fedorahosted.org/pki/ticket/304 TMS ECC infrastructure (enrollment with client-side and server-side key generation, and key archival) --- base/tps/src/cms/CertEnroll.cpp | 305 +++++++++++++++++++++++--- base/tps/src/engine/RA.cpp | 37 +++- base/tps/src/include/channel/Secure_Channel.h | 8 + 3 files changed, 311 insertions(+), 39 deletions(-) (limited to 'base/tps') diff --git a/base/tps/src/cms/CertEnroll.cpp b/base/tps/src/cms/CertEnroll.cpp index 89990d021..fb2852d9b 100644 --- a/base/tps/src/cms/CertEnroll.cpp +++ b/base/tps/src/cms/CertEnroll.cpp @@ -19,6 +19,7 @@ // --- END COPYRIGHT BLOCK --- #include +#include #include "main/RA_Session.h" #include "main/RA_Msg.h" @@ -35,6 +36,7 @@ #include "base64.h" #include "nssb64.h" #include "prlock.h" +#include "secoidt.h" #include "main/Memory.h" @@ -49,6 +51,131 @@ ReturnStatus verifyProof(SECKEYPublicKey* , SECItem* , #define TOKENDB_PUBLIC #endif /* !XP_WIN32 */ +//ECC curve information + +typedef struct curveNameTagPairStr { + char *curveName; + SECOidTag curveOidTag; +} CurveNameTagPair; + + +static CurveNameTagPair nameTagPair[] = +{ + { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, + { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, + { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, + { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, + { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, + { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, + { "prime256v1", SEC_OID_ANSIX962_EC_PRIME256V1 }, + + { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, + { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, + { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, + { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, + { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, + { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, + { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, + { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, + { "secp192r1", SEC_OID_ANSIX962_EC_PRIME192V1 }, + { "nistp192", SEC_OID_ANSIX962_EC_PRIME192V1 }, + { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, + { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, + { "nistp224", SEC_OID_SECG_EC_SECP224R1}, + { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, + { "secp256r1", SEC_OID_ANSIX962_EC_PRIME256V1 }, + { "nistp256", SEC_OID_ANSIX962_EC_PRIME256V1 }, + { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, + { "nistp384", SEC_OID_SECG_EC_SECP384R1}, + { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, + { "nistp521", SEC_OID_SECG_EC_SECP521R1}, + + { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, + { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, + { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, + { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, + { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, + { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, + { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, + { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, + { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, + { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, + { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, + { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, + { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, + { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, + { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, + { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, + { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, + { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, + { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, + { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, + + { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, + { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, + { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, + { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, + { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, + { "nistk163", SEC_OID_SECG_EC_SECT163K1}, + { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, + { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, + { "nistb163", SEC_OID_SECG_EC_SECT163R2}, + { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, + { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, + { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, + { "nistk233", SEC_OID_SECG_EC_SECT233K1}, + { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, + { "nistb233", SEC_OID_SECG_EC_SECT233R1}, + { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, + { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, + { "nistk283", SEC_OID_SECG_EC_SECT283K1}, + { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, + { "nistb283", SEC_OID_SECG_EC_SECT283R1}, + { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, + { "nistk409", SEC_OID_SECG_EC_SECT409K1}, + { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, + { "nistb409", SEC_OID_SECG_EC_SECT409R1}, + { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, + { "nistk571", SEC_OID_SECG_EC_SECT571K1}, + { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, + { "nistb571", SEC_OID_SECG_EC_SECT571R1}, + +}; + +SECKEYECParams * +CertEnroll::encode_ec_params(char *curve) +{ + SECKEYECParams *ecparams; + SECOidData *oidData = NULL; + SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ + int i, numCurves; + + if (curve && *curve) { + numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); + for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); + i++) { + if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) + curveOidTag = nameTagPair[i].curveOidTag; + } + } + + if ((curveOidTag == SEC_OID_UNKNOWN) || + (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { + return NULL; + } + + ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); + + if (!ecparams) + return NULL; + + ecparams->data[0] = SEC_ASN1_OBJECT_ID; + ecparams->data[1] = oidData->oid.len; + memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); + + return ecparams; +} + /** * Constructs handle for Certificate Enrollment */ @@ -328,8 +455,20 @@ Buffer * CertEnroll::EnrollCertificate( * Short Exponent Length * * Byte[] Exponent + * + * + * ECC KeyBlob Format (ECC Public Key) + * ---------------------------------- + * + * Byte Encoding (0 for plaintext) * - * + * Byte Key Type (10 for ECC public) + * + * Short Key Length (256, 384, 521 high byte first) + * + * Byte[] Key (W) + * + * * Signature Format (Proof) * --------------------------------------- * @@ -369,7 +508,7 @@ Buffer * CertEnroll::EnrollCertificate( ******/ SECKEYPublicKey *CertEnroll::ParsePublicKeyBlob(unsigned char *blob, - Buffer *challenge) + Buffer *challenge, bool isECC) { char configname[5000]; SECKEYPublicKey *pk = NULL; @@ -404,7 +543,7 @@ SECKEYPublicKey *CertEnroll::ParsePublicKeyBlob(unsigned char *blob, pkeyb_len = (unsigned short) ((len0 << 8) | (len1 & 0xFF)); RA::Debug(LL_PER_PDU, "CertEnroll::ParsePublicKeyBlob", - "pkeyb_len =%d",pkeyb_len); + "pkeyb_len =%d isECC: %d",pkeyb_len, isECC); if (pkeyb_len <= 0) { RA::Error("CertEnroll::ParsePublicKeyBlob", "public key blob length = %d", pkeyb_len); @@ -431,51 +570,112 @@ SECKEYPublicKey *CertEnroll::ParsePublicKeyBlob(unsigned char *blob, // convert pkeyb to pkey // 1 byte encoding, 1 byte key type, 2 bytes key length, then the key + + // for ECC + unsigned short ecc_pkey_len = 0; + // ecc key blob + unsigned char *eccpb = NULL; + + // for RSA + unsigned short mod_len = 0; + unsigned short exp_len = 0; + // public key mod blob + unsigned char * modb = NULL; + // public key exp blob + unsigned char * expb = NULL; + unsigned short pkey_offset = 4; - // now, convert lengths for modulus and exponent len0 = pkeyb[pkey_offset]; len1 = pkeyb[pkey_offset + 1]; - unsigned short mod_len = (len0 << 8 | len1); - len0 = pkeyb[pkey_offset + 2 + mod_len]; - len1 = pkeyb[pkey_offset + 2 + mod_len + 1]; - unsigned short exp_len = (len0 << 8 | len1); + if (!isECC) { + // now, convert lengths for modulus and exponent + mod_len = (len0 << 8 | len1); + len0 = pkeyb[pkey_offset + 2 + mod_len]; + len1 = pkeyb[pkey_offset + 2 + mod_len + 1]; + exp_len = (len0 << 8 | len1); - // public key mod blob - unsigned char * modb = &pkeyb[pkey_offset + 2]; + modb = &pkeyb[pkey_offset + 2]; + expb = &pkeyb[pkey_offset + 2 + mod_len + 2]; - // public key exp blob - unsigned char * expb = &pkeyb[pkey_offset + 2 + mod_len + 2]; + } else { + ecc_pkey_len = (len0 << 8 | len1); + eccpb = &pkeyb[pkey_offset + 2]; + } // construct SECItem - SECItem siMod; - siMod.type = (SECItemType) 0; - siMod.data = (unsigned char *) modb; - siMod.len = mod_len; + // for RSA + SECItem siMod; SECItem siExp; - siExp.type = (SECItemType) 0; - siExp.data = (unsigned char *)expb; - siExp.len = exp_len; - - // construct SECKEYRSAPublicKeyStr SECKEYRSAPublicKeyStr rsa_pks; - rsa_pks.modulus = siMod; - rsa_pks.publicExponent = siExp; - // construct SECKEYPublicKey - // this is to be returned + // for ECC + SECItem eccValue; + SECKEYECPublicKeyStr ecc_pks; + SECKEYECParams *ecc_key_params = NULL; + pk = (SECKEYPublicKey *) malloc(sizeof(SECKEYPublicKey)); - pk->keyType = rsaKey; - pk->pkcs11Slot = NULL; - pk->pkcs11ID = CK_INVALID_HANDLE; - pk->u.rsa = rsa_pks; + + assert(pk); + + if (!isECC) { + + siMod.type = (SECItemType) 0; + siMod.data = (unsigned char *) modb; + siMod.len = mod_len; + + siExp.type = (SECItemType) 0; + siExp.data = (unsigned char *)expb; + siExp.len = exp_len; + + // construct SECKEYRSAPublicKeyStr + rsa_pks.modulus = siMod; + rsa_pks.publicExponent = siExp; + + pk->keyType = rsaKey; + pk->pkcs11Slot = NULL; + pk->pkcs11ID = CK_INVALID_HANDLE; + pk->u.rsa = rsa_pks; + } else { + // ECC + len0 = blob[pkeyb_len_offset +4]; + len1 = blob[pkeyb_len_offset +5]; + int keyCurveSize = (len0 << 8 | len1); + + RA::Debug(LL_PER_PDU, "CertEnroll::ParsePublicKeyBlob", + "keyCurveSize =%d",keyCurveSize); + + char curve[56] = ""; + snprintf(curve, 56, "nistp%d",keyCurveSize ); + + ecc_key_params = encode_ec_params(curve); + + if (ecc_key_params == NULL) { + free(pk); + pk = NULL; + return NULL; + } + + eccValue.type = (SECItemType) 0; + eccValue.data = (unsigned char *) eccpb; + eccValue.len = ecc_pkey_len; + + ecc_pks.size = keyCurveSize; + ecc_pks.publicValue = eccValue; + ecc_pks.DEREncodedParams = *ecc_key_params; + + pk->keyType = ecKey; + pk->pkcs11Slot = NULL; + pk->pkcs11ID = CK_INVALID_HANDLE; + pk->u.ec = ecc_pks; + } PR_snprintf((char *)configname, 256, "general.verifyProof"); int verifyProofEnable = RA::GetConfigStore()->GetConfigAsInt(configname, 0x1); if (verifyProofEnable) { - rs = verifyProof(pk, &siProof, pkeyb_len, pkeyb, challenge); + rs = verifyProof(pk, &siProof, pkeyb_len, pkeyb, challenge, isECC); if (rs.status == PR_FAILURE) { RA::Error("CertEnroll::ParsePublicKeyBlob", "verify proof failed"); @@ -487,6 +687,32 @@ SECKEYPublicKey *CertEnroll::ParsePublicKeyBlob(unsigned char *blob, return pk; } +/* + * for debugging tokens + * -- list out all tokens and thier login status + */ +static SECStatus +ListModules(void) +{ + PK11SlotList *list; + PK11SlotListElement *le; + + /* get them all! */ + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,NULL); + if (list == NULL) return SECFailure; + + /* look at each slot*/ + for (le = list->head ; le; le = le->next) { + RA::Debug( LL_PER_PDU, "CertEnroll::ListModules", + " slot: %s\n, loggedIn? %d, token: %s\n", PK11_GetSlotName(le->slot), + (PK11_IsLoggedIn(le->slot, NULL) == PR_TRUE)? 1:0, + PK11_GetTokenName(le->slot)); + } + PK11_FreeSlotList(list); + + return SECSuccess; +} + /** * verify the proof. @@ -502,18 +728,24 @@ SECKEYPublicKey *CertEnroll::ParsePublicKeyBlob(unsigned char *blob, */ ReturnStatus CertEnroll::verifyProof(SECKEYPublicKey* pk, SECItem* siProof, unsigned short pkeyb_len, unsigned char* pkeyb, - Buffer* challenge) { + Buffer* challenge, bool isECC) { ReturnStatus rs; VFYContext * vc = NULL; rs.statusNum = ::VRFY_SUCCESS; rs.status = PR_SUCCESS; + // ListModules(); + // verify proof (signature) RA::Debug(LL_PER_PDU, "CertEnroll::verifyProof", "verify proof begins"); - vc = VFY_CreateContext(pk, siProof, SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE, NULL); + if(isECC) { + vc = VFY_CreateContext(pk, siProof, SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE , NULL); + } else { + vc = VFY_CreateContext(pk, siProof, SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE, NULL); + } if (vc == NULL) { RA::Error("CertEnroll::verifyProof", @@ -530,14 +762,15 @@ ReturnStatus CertEnroll::verifyProof(SECKEYPublicKey* pk, SECItem* siProof, int i =0; for (i = 0; isize()); + "VFY_End() failed pkeyb_len=%d challenge_size=%d error=%d", pkeyb_len, challenge->size(),PR_GetError()); rs.statusNum = ::VFY_UPDATE_FAILURE; rs.status = PR_FAILURE; } diff --git a/base/tps/src/engine/RA.cpp b/base/tps/src/engine/RA.cpp index f8c64f306..2502cf259 100644 --- a/base/tps/src/engine/RA.cpp +++ b/base/tps/src/engine/RA.cpp @@ -1302,7 +1302,7 @@ void RA::ServerSideKeyGen(RA_Session *session, const char* cuid, char **publicKey_s, char **wrappedPrivateKey_s, char **ivParam_s, const char *connId, - bool archive, int keysize) + bool archive, int keysize, bool isECC) { const char *FN="RA::ServerSideKeyGen"; @@ -1372,8 +1372,27 @@ void RA::ServerSideKeyGen(RA_Session *session, const char* cuid, RA::Debug(LL_PER_CONNECTION, FN, "wrappedDESKey_s=%s", wrappedDESKey_s); - PR_snprintf((char *)body, MAX_BODY_LEN, - "archive=%s&CUID=%s&userid=%s&keysize=%d&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, keysize, wrappedDESKey_s); + if (isECC) { + char *eckeycurve = NULL; + if (keysize == 521) { + eckeycurve = "nistp521"; + } else if (keysize == 384) { + eckeycurve = "nistp384"; + } else if (keysize == 256) { + eckeycurve = "nistp256"; + } else { + RA::Debug(LL_PER_CONNECTION, FN, + "unrecognized ECC keysize %d, setting to nistp256", keysize); + keysize = 256; + eckeycurve = "nistp256"; + } + PR_snprintf((char *)body, MAX_BODY_LEN, + "archive=%s&CUID=%s&userid=%s&keytype=EC&eckeycurve=%s&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, eckeycurve, wrappedDESKey_s); + } else { + PR_snprintf((char *)body, MAX_BODY_LEN, + "archive=%s&CUID=%s&userid=%s&keysize=%d&keytype=RSA&drm_trans_desKey=%s",archive?"true":"false",cuid, userid, keysize, wrappedDESKey_s); + } + RA::Debug(LL_PER_CONNECTION, FN, "sending to DRM: query=%s", body); @@ -3680,6 +3699,18 @@ loser: return newKey; } +bool RA::isAlgorithmECC(BYTE alg) +{ + bool result = false; + + if (alg == ALG_EC_F2M || alg == ALG_EC_FP) + result = true; + + RA::Debug(LL_PER_SERVER, "RA::isAlgorithmECC", " alg: %d result: %d", alg, result); + + return result; +} + bool RA::transition_allowed(int oldState, int newState) { /* parse the allowed transitions string and look for old:new */ diff --git a/base/tps/src/include/channel/Secure_Channel.h b/base/tps/src/include/channel/Secure_Channel.h index bac072407..e67f8ebaf 100644 --- a/base/tps/src/include/channel/Secure_Channel.h +++ b/base/tps/src/include/channel/Secure_Channel.h @@ -125,10 +125,18 @@ class Secure_Channel : public Channel int CreatePKCS11CertAttrs(TokenKeyType type, const char *id, const char *label, Buffer *keyid); Buffer CreatePKCS11PriKeyAttrsBuffer(TokenKeyType type, const char *id, const char *label, Buffer *keyid, Buffer *modulus, const char *opType, const char *tokenType, const char *keyTypePrefix); + + Buffer CreatePKCS11ECCPriKeyAttrsBuffer(TokenKeyType type, const char *id, const char *label, Buffer *keyid, + SECKEYECParams *ecParams, const char *opType, const char *tokenType, const char *keyTypePrefix); + int CreatePKCS11PriKeyAttrs(TokenKeyType type, const char *id, const char *label, Buffer *keyid, Buffer *modulus, const char *opType, const char *tokenType, const char *keyTypePrefix); Buffer CreatePKCS11PubKeyAttrsBuffer(TokenKeyType type, const char *id, const char *label, Buffer *keyid, Buffer *exponent, Buffer *modulus, const char *opType, const char *tokenType, const char *keyTypePrefix); + + Buffer CreatePKCS11ECCPubKeyAttrsBuffer(TokenKeyType key_type, const char *id, const char *label, Buffer *keyid, SECKEYECPublicKey *publicKey, + SECKEYECParams *ecParams, const char *opType, const char *tokenType, const char *keyTypePrefix); + int CreatePKCS11PubKeyAttrs(TokenKeyType type, const char *id, const char *label, Buffer *keyid, Buffer *exponent, Buffer *modulus, const char *opType, const char *tokenType, const char *keyTypePrefix); APDU_Response *SendTokenAPU(APDU *apdu); -- cgit