Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- |
michael@0 | 2 | * |
michael@0 | 3 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 6 | |
michael@0 | 7 | #include "secdert.h" |
michael@0 | 8 | #include "nspr.h" |
michael@0 | 9 | #include "nsNSSComponent.h" // for PIPNSS string bundle calls. |
michael@0 | 10 | #include "keyhi.h" |
michael@0 | 11 | #include "secder.h" |
michael@0 | 12 | #include "cryptohi.h" |
michael@0 | 13 | #include "base64.h" |
michael@0 | 14 | #include "secasn1.h" |
michael@0 | 15 | #include "pk11pqg.h" |
michael@0 | 16 | #include "nsKeygenHandler.h" |
michael@0 | 17 | #include "nsIServiceManager.h" |
michael@0 | 18 | #include "nsIDOMHTMLSelectElement.h" |
michael@0 | 19 | #include "nsIContent.h" |
michael@0 | 20 | #include "nsKeygenThread.h" |
michael@0 | 21 | #include "nsReadableUtils.h" |
michael@0 | 22 | #include "nsUnicharUtils.h" |
michael@0 | 23 | #include "nsCRT.h" |
michael@0 | 24 | #include "nsITokenDialogs.h" |
michael@0 | 25 | #include "nsIGenKeypairInfoDlg.h" |
michael@0 | 26 | #include "nsNSSShutDown.h" |
michael@0 | 27 | |
michael@0 | 28 | //These defines are taken from the PKCS#11 spec |
michael@0 | 29 | #define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000 |
michael@0 | 30 | #define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 |
michael@0 | 31 | #define CKM_DSA_KEY_PAIR_GEN 0x00000010 |
michael@0 | 32 | |
michael@0 | 33 | DERTemplate SECAlgorithmIDTemplate[] = { |
michael@0 | 34 | { DER_SEQUENCE, |
michael@0 | 35 | 0, nullptr, sizeof(SECAlgorithmID) }, |
michael@0 | 36 | { DER_OBJECT_ID, |
michael@0 | 37 | offsetof(SECAlgorithmID,algorithm), }, |
michael@0 | 38 | { DER_OPTIONAL | DER_ANY, |
michael@0 | 39 | offsetof(SECAlgorithmID,parameters), }, |
michael@0 | 40 | { 0, } |
michael@0 | 41 | }; |
michael@0 | 42 | |
michael@0 | 43 | DERTemplate CERTSubjectPublicKeyInfoTemplate[] = { |
michael@0 | 44 | { DER_SEQUENCE, |
michael@0 | 45 | 0, nullptr, sizeof(CERTSubjectPublicKeyInfo) }, |
michael@0 | 46 | { DER_INLINE, |
michael@0 | 47 | offsetof(CERTSubjectPublicKeyInfo,algorithm), |
michael@0 | 48 | SECAlgorithmIDTemplate, }, |
michael@0 | 49 | { DER_BIT_STRING, |
michael@0 | 50 | offsetof(CERTSubjectPublicKeyInfo,subjectPublicKey), }, |
michael@0 | 51 | { 0, } |
michael@0 | 52 | }; |
michael@0 | 53 | |
michael@0 | 54 | DERTemplate CERTPublicKeyAndChallengeTemplate[] = |
michael@0 | 55 | { |
michael@0 | 56 | { DER_SEQUENCE, 0, nullptr, sizeof(CERTPublicKeyAndChallenge) }, |
michael@0 | 57 | { DER_ANY, offsetof(CERTPublicKeyAndChallenge,spki), }, |
michael@0 | 58 | { DER_IA5_STRING, offsetof(CERTPublicKeyAndChallenge,challenge), }, |
michael@0 | 59 | { 0, } |
michael@0 | 60 | }; |
michael@0 | 61 | |
michael@0 | 62 | const SEC_ASN1Template SECKEY_PQGParamsTemplate[] = { |
michael@0 | 63 | { SEC_ASN1_SEQUENCE, 0, nullptr, sizeof(PQGParams) }, |
michael@0 | 64 | { SEC_ASN1_INTEGER, offsetof(PQGParams,prime) }, |
michael@0 | 65 | { SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) }, |
michael@0 | 66 | { SEC_ASN1_INTEGER, offsetof(PQGParams,base) }, |
michael@0 | 67 | { 0, } |
michael@0 | 68 | }; |
michael@0 | 69 | |
michael@0 | 70 | |
michael@0 | 71 | static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); |
michael@0 | 72 | |
michael@0 | 73 | static PQGParams * |
michael@0 | 74 | decode_pqg_params(char *aStr) |
michael@0 | 75 | { |
michael@0 | 76 | unsigned char *buf = nullptr; |
michael@0 | 77 | unsigned int len; |
michael@0 | 78 | PLArenaPool *arena = nullptr; |
michael@0 | 79 | PQGParams *params = nullptr; |
michael@0 | 80 | SECStatus status; |
michael@0 | 81 | |
michael@0 | 82 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
michael@0 | 83 | if (!arena) |
michael@0 | 84 | return nullptr; |
michael@0 | 85 | |
michael@0 | 86 | params = static_cast<PQGParams*>(PORT_ArenaZAlloc(arena, sizeof(PQGParams))); |
michael@0 | 87 | if (!params) |
michael@0 | 88 | goto loser; |
michael@0 | 89 | params->arena = arena; |
michael@0 | 90 | |
michael@0 | 91 | buf = ATOB_AsciiToData(aStr, &len); |
michael@0 | 92 | if ((!buf) || (len == 0)) |
michael@0 | 93 | goto loser; |
michael@0 | 94 | |
michael@0 | 95 | status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, (const char*)buf, len); |
michael@0 | 96 | if (status != SECSuccess) |
michael@0 | 97 | goto loser; |
michael@0 | 98 | |
michael@0 | 99 | return params; |
michael@0 | 100 | |
michael@0 | 101 | loser: |
michael@0 | 102 | if (arena) { |
michael@0 | 103 | PORT_FreeArena(arena, false); |
michael@0 | 104 | } |
michael@0 | 105 | if (buf) { |
michael@0 | 106 | PR_Free(buf); |
michael@0 | 107 | } |
michael@0 | 108 | return nullptr; |
michael@0 | 109 | } |
michael@0 | 110 | |
michael@0 | 111 | static int |
michael@0 | 112 | pqg_prime_bits(char *str) |
michael@0 | 113 | { |
michael@0 | 114 | PQGParams *params = nullptr; |
michael@0 | 115 | int primeBits = 0, i; |
michael@0 | 116 | |
michael@0 | 117 | params = decode_pqg_params(str); |
michael@0 | 118 | if (!params) |
michael@0 | 119 | goto done; /* lose */ |
michael@0 | 120 | |
michael@0 | 121 | for (i = 0; params->prime.data[i] == 0; i++) |
michael@0 | 122 | /* empty */; |
michael@0 | 123 | primeBits = (params->prime.len - i) * 8; |
michael@0 | 124 | |
michael@0 | 125 | done: |
michael@0 | 126 | if (params) |
michael@0 | 127 | PK11_PQG_DestroyParams(params); |
michael@0 | 128 | return primeBits; |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | typedef struct curveNameTagPairStr { |
michael@0 | 132 | const char *curveName; |
michael@0 | 133 | SECOidTag curveOidTag; |
michael@0 | 134 | } CurveNameTagPair; |
michael@0 | 135 | |
michael@0 | 136 | static CurveNameTagPair nameTagPair[] = |
michael@0 | 137 | { |
michael@0 | 138 | { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, |
michael@0 | 139 | { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, |
michael@0 | 140 | { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, |
michael@0 | 141 | { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, |
michael@0 | 142 | { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, |
michael@0 | 143 | { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, |
michael@0 | 144 | { "prime256v1", SEC_OID_ANSIX962_EC_PRIME256V1 }, |
michael@0 | 145 | |
michael@0 | 146 | { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, |
michael@0 | 147 | { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, |
michael@0 | 148 | { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, |
michael@0 | 149 | { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, |
michael@0 | 150 | { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, |
michael@0 | 151 | { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, |
michael@0 | 152 | { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, |
michael@0 | 153 | { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, |
michael@0 | 154 | { "secp192r1", SEC_OID_ANSIX962_EC_PRIME192V1 }, |
michael@0 | 155 | { "nistp192", SEC_OID_ANSIX962_EC_PRIME192V1 }, |
michael@0 | 156 | { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, |
michael@0 | 157 | { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, |
michael@0 | 158 | { "nistp224", SEC_OID_SECG_EC_SECP224R1}, |
michael@0 | 159 | { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, |
michael@0 | 160 | { "secp256r1", SEC_OID_ANSIX962_EC_PRIME256V1 }, |
michael@0 | 161 | { "nistp256", SEC_OID_ANSIX962_EC_PRIME256V1 }, |
michael@0 | 162 | { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, |
michael@0 | 163 | { "nistp384", SEC_OID_SECG_EC_SECP384R1}, |
michael@0 | 164 | { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, |
michael@0 | 165 | { "nistp521", SEC_OID_SECG_EC_SECP521R1}, |
michael@0 | 166 | |
michael@0 | 167 | { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, |
michael@0 | 168 | { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, |
michael@0 | 169 | { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, |
michael@0 | 170 | { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, |
michael@0 | 171 | { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, |
michael@0 | 172 | { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, |
michael@0 | 173 | { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, |
michael@0 | 174 | { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, |
michael@0 | 175 | { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, |
michael@0 | 176 | { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, |
michael@0 | 177 | { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, |
michael@0 | 178 | { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, |
michael@0 | 179 | { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, |
michael@0 | 180 | { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, |
michael@0 | 181 | { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, |
michael@0 | 182 | { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, |
michael@0 | 183 | { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, |
michael@0 | 184 | { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, |
michael@0 | 185 | { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, |
michael@0 | 186 | { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, |
michael@0 | 187 | |
michael@0 | 188 | { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, |
michael@0 | 189 | { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, |
michael@0 | 190 | { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, |
michael@0 | 191 | { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, |
michael@0 | 192 | { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, |
michael@0 | 193 | { "nistk163", SEC_OID_SECG_EC_SECT163K1}, |
michael@0 | 194 | { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, |
michael@0 | 195 | { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, |
michael@0 | 196 | { "nistb163", SEC_OID_SECG_EC_SECT163R2}, |
michael@0 | 197 | { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, |
michael@0 | 198 | { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, |
michael@0 | 199 | { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, |
michael@0 | 200 | { "nistk233", SEC_OID_SECG_EC_SECT233K1}, |
michael@0 | 201 | { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, |
michael@0 | 202 | { "nistb233", SEC_OID_SECG_EC_SECT233R1}, |
michael@0 | 203 | { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, |
michael@0 | 204 | { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, |
michael@0 | 205 | { "nistk283", SEC_OID_SECG_EC_SECT283K1}, |
michael@0 | 206 | { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, |
michael@0 | 207 | { "nistb283", SEC_OID_SECG_EC_SECT283R1}, |
michael@0 | 208 | { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, |
michael@0 | 209 | { "nistk409", SEC_OID_SECG_EC_SECT409K1}, |
michael@0 | 210 | { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, |
michael@0 | 211 | { "nistb409", SEC_OID_SECG_EC_SECT409R1}, |
michael@0 | 212 | { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, |
michael@0 | 213 | { "nistk571", SEC_OID_SECG_EC_SECT571K1}, |
michael@0 | 214 | { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, |
michael@0 | 215 | { "nistb571", SEC_OID_SECG_EC_SECT571R1}, |
michael@0 | 216 | |
michael@0 | 217 | }; |
michael@0 | 218 | |
michael@0 | 219 | SECKEYECParams * |
michael@0 | 220 | decode_ec_params(const char *curve) |
michael@0 | 221 | { |
michael@0 | 222 | SECKEYECParams *ecparams; |
michael@0 | 223 | SECOidData *oidData = nullptr; |
michael@0 | 224 | SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ |
michael@0 | 225 | int i, numCurves; |
michael@0 | 226 | |
michael@0 | 227 | if (curve && *curve) { |
michael@0 | 228 | numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); |
michael@0 | 229 | for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); |
michael@0 | 230 | i++) { |
michael@0 | 231 | if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) |
michael@0 | 232 | curveOidTag = nameTagPair[i].curveOidTag; |
michael@0 | 233 | } |
michael@0 | 234 | } |
michael@0 | 235 | |
michael@0 | 236 | /* Return nullptr if curve name is not recognized */ |
michael@0 | 237 | if ((curveOidTag == SEC_OID_UNKNOWN) || |
michael@0 | 238 | (oidData = SECOID_FindOIDByTag(curveOidTag)) == nullptr) { |
michael@0 | 239 | return nullptr; |
michael@0 | 240 | } |
michael@0 | 241 | |
michael@0 | 242 | ecparams = SECITEM_AllocItem(nullptr, nullptr, (2 + oidData->oid.len)); |
michael@0 | 243 | |
michael@0 | 244 | if (!ecparams) |
michael@0 | 245 | return nullptr; |
michael@0 | 246 | |
michael@0 | 247 | /* |
michael@0 | 248 | * ecparams->data needs to contain the ASN encoding of an object ID (OID) |
michael@0 | 249 | * representing the named curve. The actual OID is in |
michael@0 | 250 | * oidData->oid.data so we simply prepend 0x06 and OID length |
michael@0 | 251 | */ |
michael@0 | 252 | ecparams->data[0] = SEC_ASN1_OBJECT_ID; |
michael@0 | 253 | ecparams->data[1] = oidData->oid.len; |
michael@0 | 254 | memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); |
michael@0 | 255 | |
michael@0 | 256 | return ecparams; |
michael@0 | 257 | } |
michael@0 | 258 | |
michael@0 | 259 | NS_IMPL_ISUPPORTS(nsKeygenFormProcessor, nsIFormProcessor) |
michael@0 | 260 | |
michael@0 | 261 | nsKeygenFormProcessor::nsKeygenFormProcessor() |
michael@0 | 262 | { |
michael@0 | 263 | m_ctx = new PipUIContext(); |
michael@0 | 264 | |
michael@0 | 265 | } |
michael@0 | 266 | |
michael@0 | 267 | nsKeygenFormProcessor::~nsKeygenFormProcessor() |
michael@0 | 268 | { |
michael@0 | 269 | } |
michael@0 | 270 | |
michael@0 | 271 | nsresult |
michael@0 | 272 | nsKeygenFormProcessor::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult) |
michael@0 | 273 | { |
michael@0 | 274 | nsresult rv; |
michael@0 | 275 | NS_ENSURE_NO_AGGREGATION(aOuter); |
michael@0 | 276 | nsKeygenFormProcessor* formProc = new nsKeygenFormProcessor(); |
michael@0 | 277 | |
michael@0 | 278 | nsCOMPtr<nsISupports> stabilize = formProc; |
michael@0 | 279 | rv = formProc->Init(); |
michael@0 | 280 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 281 | rv = formProc->QueryInterface(aIID, aResult); |
michael@0 | 282 | } |
michael@0 | 283 | return rv; |
michael@0 | 284 | } |
michael@0 | 285 | |
michael@0 | 286 | nsresult |
michael@0 | 287 | nsKeygenFormProcessor::Init() |
michael@0 | 288 | { |
michael@0 | 289 | static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); |
michael@0 | 290 | |
michael@0 | 291 | nsresult rv; |
michael@0 | 292 | |
michael@0 | 293 | nsCOMPtr<nsINSSComponent> nssComponent; |
michael@0 | 294 | nssComponent = do_GetService(kNSSComponentCID, &rv); |
michael@0 | 295 | if (NS_FAILED(rv)) |
michael@0 | 296 | return rv; |
michael@0 | 297 | |
michael@0 | 298 | // Init possible key size choices. |
michael@0 | 299 | nssComponent->GetPIPNSSBundleString("HighGrade", mSECKeySizeChoiceList[0].name); |
michael@0 | 300 | mSECKeySizeChoiceList[0].size = 2048; |
michael@0 | 301 | |
michael@0 | 302 | nssComponent->GetPIPNSSBundleString("MediumGrade", mSECKeySizeChoiceList[1].name); |
michael@0 | 303 | mSECKeySizeChoiceList[1].size = 1024; |
michael@0 | 304 | |
michael@0 | 305 | return NS_OK; |
michael@0 | 306 | } |
michael@0 | 307 | |
michael@0 | 308 | nsresult |
michael@0 | 309 | nsKeygenFormProcessor::GetSlot(uint32_t aMechanism, PK11SlotInfo** aSlot) |
michael@0 | 310 | { |
michael@0 | 311 | return GetSlotWithMechanism(aMechanism,m_ctx,aSlot); |
michael@0 | 312 | } |
michael@0 | 313 | |
michael@0 | 314 | |
michael@0 | 315 | uint32_t MapGenMechToAlgoMech(uint32_t mechanism) |
michael@0 | 316 | { |
michael@0 | 317 | uint32_t searchMech; |
michael@0 | 318 | |
michael@0 | 319 | /* We are interested in slots based on the ability to perform |
michael@0 | 320 | a given algorithm, not on their ability to generate keys usable |
michael@0 | 321 | by that algorithm. Therefore, map keygen-specific mechanism tags |
michael@0 | 322 | to tags for the corresponding crypto algorthm. */ |
michael@0 | 323 | switch(mechanism) |
michael@0 | 324 | { |
michael@0 | 325 | case CKM_RSA_PKCS_KEY_PAIR_GEN: |
michael@0 | 326 | searchMech = CKM_RSA_PKCS; |
michael@0 | 327 | break; |
michael@0 | 328 | case CKM_DSA_KEY_PAIR_GEN: |
michael@0 | 329 | searchMech = CKM_DSA; |
michael@0 | 330 | break; |
michael@0 | 331 | case CKM_RC4_KEY_GEN: |
michael@0 | 332 | searchMech = CKM_RC4; |
michael@0 | 333 | break; |
michael@0 | 334 | case CKM_DH_PKCS_KEY_PAIR_GEN: |
michael@0 | 335 | searchMech = CKM_DH_PKCS_DERIVE; /* ### mwelch is this right? */ |
michael@0 | 336 | break; |
michael@0 | 337 | case CKM_DES_KEY_GEN: |
michael@0 | 338 | /* What do we do about DES keygen? Right now, we're just using |
michael@0 | 339 | DES_KEY_GEN to look for tokens, because otherwise we'll have |
michael@0 | 340 | to search the token list three times. */ |
michael@0 | 341 | case CKM_EC_KEY_PAIR_GEN: |
michael@0 | 342 | /* The default should also work for EC key pair generation. */ |
michael@0 | 343 | default: |
michael@0 | 344 | searchMech = mechanism; |
michael@0 | 345 | break; |
michael@0 | 346 | } |
michael@0 | 347 | return searchMech; |
michael@0 | 348 | } |
michael@0 | 349 | |
michael@0 | 350 | |
michael@0 | 351 | nsresult |
michael@0 | 352 | GetSlotWithMechanism(uint32_t aMechanism, |
michael@0 | 353 | nsIInterfaceRequestor *m_ctx, |
michael@0 | 354 | PK11SlotInfo** aSlot) |
michael@0 | 355 | { |
michael@0 | 356 | nsNSSShutDownPreventionLock locker; |
michael@0 | 357 | PK11SlotList * slotList = nullptr; |
michael@0 | 358 | char16_t** tokenNameList = nullptr; |
michael@0 | 359 | nsITokenDialogs * dialogs; |
michael@0 | 360 | char16_t *unicodeTokenChosen; |
michael@0 | 361 | PK11SlotListElement *slotElement, *tmpSlot; |
michael@0 | 362 | uint32_t numSlots = 0, i = 0; |
michael@0 | 363 | bool canceled; |
michael@0 | 364 | nsresult rv = NS_OK; |
michael@0 | 365 | |
michael@0 | 366 | *aSlot = nullptr; |
michael@0 | 367 | |
michael@0 | 368 | // Get the slot |
michael@0 | 369 | slotList = PK11_GetAllTokens(MapGenMechToAlgoMech(aMechanism), |
michael@0 | 370 | true, true, m_ctx); |
michael@0 | 371 | if (!slotList || !slotList->head) { |
michael@0 | 372 | rv = NS_ERROR_FAILURE; |
michael@0 | 373 | goto loser; |
michael@0 | 374 | } |
michael@0 | 375 | |
michael@0 | 376 | if (!slotList->head->next) { |
michael@0 | 377 | /* only one slot available, just return it */ |
michael@0 | 378 | *aSlot = slotList->head->slot; |
michael@0 | 379 | } else { |
michael@0 | 380 | // Gerenate a list of slots and ask the user to choose // |
michael@0 | 381 | tmpSlot = slotList->head; |
michael@0 | 382 | while (tmpSlot) { |
michael@0 | 383 | numSlots++; |
michael@0 | 384 | tmpSlot = tmpSlot->next; |
michael@0 | 385 | } |
michael@0 | 386 | |
michael@0 | 387 | // Allocate the slot name buffer // |
michael@0 | 388 | tokenNameList = static_cast<char16_t**>(nsMemory::Alloc(sizeof(char16_t *) * numSlots)); |
michael@0 | 389 | if (!tokenNameList) { |
michael@0 | 390 | rv = NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 391 | goto loser; |
michael@0 | 392 | } |
michael@0 | 393 | |
michael@0 | 394 | i = 0; |
michael@0 | 395 | slotElement = PK11_GetFirstSafe(slotList); |
michael@0 | 396 | while (slotElement) { |
michael@0 | 397 | tokenNameList[i] = UTF8ToNewUnicode(nsDependentCString(PK11_GetTokenName(slotElement->slot))); |
michael@0 | 398 | slotElement = PK11_GetNextSafe(slotList, slotElement, false); |
michael@0 | 399 | if (tokenNameList[i]) |
michael@0 | 400 | i++; |
michael@0 | 401 | else { |
michael@0 | 402 | // OOM. adjust numSlots so we don't free unallocated memory. |
michael@0 | 403 | numSlots = i; |
michael@0 | 404 | PK11_FreeSlotListElement(slotList, slotElement); |
michael@0 | 405 | rv = NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 406 | goto loser; |
michael@0 | 407 | } |
michael@0 | 408 | } |
michael@0 | 409 | |
michael@0 | 410 | /* Throw up the token list dialog and get back the token */ |
michael@0 | 411 | rv = getNSSDialogs((void**)&dialogs, |
michael@0 | 412 | NS_GET_IID(nsITokenDialogs), |
michael@0 | 413 | NS_TOKENDIALOGS_CONTRACTID); |
michael@0 | 414 | |
michael@0 | 415 | if (NS_FAILED(rv)) goto loser; |
michael@0 | 416 | |
michael@0 | 417 | { |
michael@0 | 418 | nsPSMUITracker tracker; |
michael@0 | 419 | if (!tokenNameList || !*tokenNameList) { |
michael@0 | 420 | rv = NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 421 | } |
michael@0 | 422 | else if (tracker.isUIForbidden()) { |
michael@0 | 423 | rv = NS_ERROR_NOT_AVAILABLE; |
michael@0 | 424 | } |
michael@0 | 425 | else { |
michael@0 | 426 | rv = dialogs->ChooseToken(m_ctx, (const char16_t**)tokenNameList, numSlots, &unicodeTokenChosen, &canceled); |
michael@0 | 427 | } |
michael@0 | 428 | } |
michael@0 | 429 | NS_RELEASE(dialogs); |
michael@0 | 430 | if (NS_FAILED(rv)) goto loser; |
michael@0 | 431 | |
michael@0 | 432 | if (canceled) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; } |
michael@0 | 433 | |
michael@0 | 434 | // Get the slot // |
michael@0 | 435 | slotElement = PK11_GetFirstSafe(slotList); |
michael@0 | 436 | nsAutoString tokenStr(unicodeTokenChosen); |
michael@0 | 437 | while (slotElement) { |
michael@0 | 438 | if (tokenStr.Equals(NS_ConvertUTF8toUTF16(PK11_GetTokenName(slotElement->slot)))) { |
michael@0 | 439 | *aSlot = slotElement->slot; |
michael@0 | 440 | PK11_FreeSlotListElement(slotList, slotElement); |
michael@0 | 441 | break; |
michael@0 | 442 | } |
michael@0 | 443 | slotElement = PK11_GetNextSafe(slotList, slotElement, false); |
michael@0 | 444 | } |
michael@0 | 445 | if(!(*aSlot)) { |
michael@0 | 446 | rv = NS_ERROR_FAILURE; |
michael@0 | 447 | goto loser; |
michael@0 | 448 | } |
michael@0 | 449 | } |
michael@0 | 450 | |
michael@0 | 451 | // Get a reference to the slot // |
michael@0 | 452 | PK11_ReferenceSlot(*aSlot); |
michael@0 | 453 | loser: |
michael@0 | 454 | if (slotList) { |
michael@0 | 455 | PK11_FreeSlotList(slotList); |
michael@0 | 456 | } |
michael@0 | 457 | if (tokenNameList) { |
michael@0 | 458 | NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(numSlots, tokenNameList); |
michael@0 | 459 | } |
michael@0 | 460 | return rv; |
michael@0 | 461 | } |
michael@0 | 462 | |
michael@0 | 463 | nsresult |
michael@0 | 464 | nsKeygenFormProcessor::GetPublicKey(nsAString& aValue, nsAString& aChallenge, |
michael@0 | 465 | nsAFlatString& aKeyType, |
michael@0 | 466 | nsAString& aOutPublicKey, nsAString& aKeyParams) |
michael@0 | 467 | { |
michael@0 | 468 | nsNSSShutDownPreventionLock locker; |
michael@0 | 469 | nsresult rv = NS_ERROR_FAILURE; |
michael@0 | 470 | char *keystring = nullptr; |
michael@0 | 471 | char *keyparamsString = nullptr, *str = nullptr; |
michael@0 | 472 | uint32_t keyGenMechanism; |
michael@0 | 473 | int32_t primeBits; |
michael@0 | 474 | PK11SlotInfo *slot = nullptr; |
michael@0 | 475 | PK11RSAGenParams rsaParams; |
michael@0 | 476 | SECOidTag algTag; |
michael@0 | 477 | int keysize = 0; |
michael@0 | 478 | void *params; |
michael@0 | 479 | SECKEYPrivateKey *privateKey = nullptr; |
michael@0 | 480 | SECKEYPublicKey *publicKey = nullptr; |
michael@0 | 481 | CERTSubjectPublicKeyInfo *spkInfo = nullptr; |
michael@0 | 482 | PLArenaPool *arena = nullptr; |
michael@0 | 483 | SECStatus sec_rv = SECFailure; |
michael@0 | 484 | SECItem spkiItem; |
michael@0 | 485 | SECItem pkacItem; |
michael@0 | 486 | SECItem signedItem; |
michael@0 | 487 | CERTPublicKeyAndChallenge pkac; |
michael@0 | 488 | pkac.challenge.data = nullptr; |
michael@0 | 489 | nsIGeneratingKeypairInfoDialogs * dialogs; |
michael@0 | 490 | nsKeygenThread *KeygenRunnable = 0; |
michael@0 | 491 | nsCOMPtr<nsIKeygenThread> runnable; |
michael@0 | 492 | |
michael@0 | 493 | // permanent and sensitive flags for keygen |
michael@0 | 494 | PK11AttrFlags attrFlags = PK11_ATTR_TOKEN | PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE; |
michael@0 | 495 | |
michael@0 | 496 | // Get the key size // |
michael@0 | 497 | for (size_t i = 0; i < number_of_key_size_choices; ++i) { |
michael@0 | 498 | if (aValue.Equals(mSECKeySizeChoiceList[i].name)) { |
michael@0 | 499 | keysize = mSECKeySizeChoiceList[i].size; |
michael@0 | 500 | break; |
michael@0 | 501 | } |
michael@0 | 502 | } |
michael@0 | 503 | if (!keysize) { |
michael@0 | 504 | goto loser; |
michael@0 | 505 | } |
michael@0 | 506 | |
michael@0 | 507 | arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
michael@0 | 508 | if (!arena) { |
michael@0 | 509 | goto loser; |
michael@0 | 510 | } |
michael@0 | 511 | |
michael@0 | 512 | // Set the keygen mechanism |
michael@0 | 513 | if (aKeyType.IsEmpty() || aKeyType.LowerCaseEqualsLiteral("rsa")) { |
michael@0 | 514 | keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; |
michael@0 | 515 | } else if (aKeyType.LowerCaseEqualsLiteral("dsa")) { |
michael@0 | 516 | char * end; |
michael@0 | 517 | keyparamsString = ToNewCString(aKeyParams); |
michael@0 | 518 | if (!keyparamsString) { |
michael@0 | 519 | rv = NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 520 | goto loser; |
michael@0 | 521 | } |
michael@0 | 522 | |
michael@0 | 523 | keyGenMechanism = CKM_DSA_KEY_PAIR_GEN; |
michael@0 | 524 | if (strcmp(keyparamsString, "null") == 0) |
michael@0 | 525 | goto loser; |
michael@0 | 526 | str = keyparamsString; |
michael@0 | 527 | bool found_match = false; |
michael@0 | 528 | do { |
michael@0 | 529 | end = strchr(str, ','); |
michael@0 | 530 | if (end) |
michael@0 | 531 | *end = '\0'; |
michael@0 | 532 | primeBits = pqg_prime_bits(str); |
michael@0 | 533 | if (keysize == primeBits) { |
michael@0 | 534 | found_match = true; |
michael@0 | 535 | break; |
michael@0 | 536 | } |
michael@0 | 537 | str = end + 1; |
michael@0 | 538 | } while (end); |
michael@0 | 539 | if (!found_match) { |
michael@0 | 540 | goto loser; |
michael@0 | 541 | } |
michael@0 | 542 | } else if (aKeyType.LowerCaseEqualsLiteral("ec")) { |
michael@0 | 543 | keyparamsString = ToNewCString(aKeyParams); |
michael@0 | 544 | if (!keyparamsString) { |
michael@0 | 545 | rv = NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 546 | goto loser; |
michael@0 | 547 | } |
michael@0 | 548 | |
michael@0 | 549 | keyGenMechanism = CKM_EC_KEY_PAIR_GEN; |
michael@0 | 550 | /* ecParams are initialized later */ |
michael@0 | 551 | } else { |
michael@0 | 552 | goto loser; |
michael@0 | 553 | } |
michael@0 | 554 | |
michael@0 | 555 | // Get the slot |
michael@0 | 556 | rv = GetSlot(keyGenMechanism, &slot); |
michael@0 | 557 | if (NS_FAILED(rv)) { |
michael@0 | 558 | goto loser; |
michael@0 | 559 | } |
michael@0 | 560 | switch (keyGenMechanism) { |
michael@0 | 561 | case CKM_RSA_PKCS_KEY_PAIR_GEN: |
michael@0 | 562 | rsaParams.keySizeInBits = keysize; |
michael@0 | 563 | rsaParams.pe = DEFAULT_RSA_KEYGEN_PE; |
michael@0 | 564 | algTag = DEFAULT_RSA_KEYGEN_ALG; |
michael@0 | 565 | params = &rsaParams; |
michael@0 | 566 | break; |
michael@0 | 567 | case CKM_DSA_KEY_PAIR_GEN: |
michael@0 | 568 | // XXX Fix this! XXX // |
michael@0 | 569 | goto loser; |
michael@0 | 570 | case CKM_EC_KEY_PAIR_GEN: |
michael@0 | 571 | /* XXX We ought to rethink how the KEYGEN tag is |
michael@0 | 572 | * displayed. The pulldown selections presented |
michael@0 | 573 | * to the user must depend on the keytype. |
michael@0 | 574 | * The displayed selection could be picked |
michael@0 | 575 | * from the keyparams attribute (this is currently called |
michael@0 | 576 | * the pqg attribute). |
michael@0 | 577 | * For now, we pick ecparams from the keyparams field |
michael@0 | 578 | * if it specifies a valid supported curve, or else |
michael@0 | 579 | * we pick one of secp384r1, secp256r1 or secp192r1 |
michael@0 | 580 | * respectively depending on the user's selection |
michael@0 | 581 | * (High, Medium, Low). |
michael@0 | 582 | * (RSA uses RSA-2048, RSA-1024 and RSA-512 for historical |
michael@0 | 583 | * reasons, while ECC choices represent a stronger mapping) |
michael@0 | 584 | * NOTE: The user's selection |
michael@0 | 585 | * is silently ignored when a valid curve is presented |
michael@0 | 586 | * in keyparams. |
michael@0 | 587 | */ |
michael@0 | 588 | if ((params = decode_ec_params(keyparamsString)) == nullptr) { |
michael@0 | 589 | /* The keyparams attribute did not specify a valid |
michael@0 | 590 | * curve name so use a curve based on the keysize. |
michael@0 | 591 | * NOTE: Here keysize is used only as an indication of |
michael@0 | 592 | * High/Medium/Low strength; elliptic curve |
michael@0 | 593 | * cryptography uses smaller keys than RSA to provide |
michael@0 | 594 | * equivalent security. |
michael@0 | 595 | */ |
michael@0 | 596 | switch (keysize) { |
michael@0 | 597 | case 2048: |
michael@0 | 598 | params = decode_ec_params("secp384r1"); |
michael@0 | 599 | break; |
michael@0 | 600 | case 1024: |
michael@0 | 601 | case 512: |
michael@0 | 602 | params = decode_ec_params("secp256r1"); |
michael@0 | 603 | break; |
michael@0 | 604 | } |
michael@0 | 605 | } |
michael@0 | 606 | /* XXX The signature algorithm ought to choose the hashing |
michael@0 | 607 | * algorithm based on key size once ECDSA variations based |
michael@0 | 608 | * on SHA256 SHA384 and SHA512 are standardized. |
michael@0 | 609 | */ |
michael@0 | 610 | algTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; |
michael@0 | 611 | break; |
michael@0 | 612 | default: |
michael@0 | 613 | goto loser; |
michael@0 | 614 | } |
michael@0 | 615 | |
michael@0 | 616 | /* Make sure token is initialized. */ |
michael@0 | 617 | rv = setPassword(slot, m_ctx); |
michael@0 | 618 | if (NS_FAILED(rv)) |
michael@0 | 619 | goto loser; |
michael@0 | 620 | |
michael@0 | 621 | sec_rv = PK11_Authenticate(slot, true, m_ctx); |
michael@0 | 622 | if (sec_rv != SECSuccess) { |
michael@0 | 623 | goto loser; |
michael@0 | 624 | } |
michael@0 | 625 | |
michael@0 | 626 | rv = getNSSDialogs((void**)&dialogs, |
michael@0 | 627 | NS_GET_IID(nsIGeneratingKeypairInfoDialogs), |
michael@0 | 628 | NS_GENERATINGKEYPAIRINFODIALOGS_CONTRACTID); |
michael@0 | 629 | |
michael@0 | 630 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 631 | KeygenRunnable = new nsKeygenThread(); |
michael@0 | 632 | NS_IF_ADDREF(KeygenRunnable); |
michael@0 | 633 | } |
michael@0 | 634 | |
michael@0 | 635 | if (NS_FAILED(rv) || !KeygenRunnable) { |
michael@0 | 636 | rv = NS_OK; |
michael@0 | 637 | privateKey = PK11_GenerateKeyPairWithFlags(slot, keyGenMechanism, params, |
michael@0 | 638 | &publicKey, attrFlags, m_ctx); |
michael@0 | 639 | } else { |
michael@0 | 640 | KeygenRunnable->SetParams( slot, attrFlags, nullptr, 0, |
michael@0 | 641 | keyGenMechanism, params, m_ctx ); |
michael@0 | 642 | |
michael@0 | 643 | runnable = do_QueryInterface(KeygenRunnable); |
michael@0 | 644 | |
michael@0 | 645 | if (runnable) { |
michael@0 | 646 | { |
michael@0 | 647 | nsPSMUITracker tracker; |
michael@0 | 648 | if (tracker.isUIForbidden()) { |
michael@0 | 649 | rv = NS_ERROR_NOT_AVAILABLE; |
michael@0 | 650 | } |
michael@0 | 651 | else { |
michael@0 | 652 | rv = dialogs->DisplayGeneratingKeypairInfo(m_ctx, runnable); |
michael@0 | 653 | // We call join on the thread, |
michael@0 | 654 | // so we can be sure that no simultaneous access to the passed parameters will happen. |
michael@0 | 655 | KeygenRunnable->Join(); |
michael@0 | 656 | } |
michael@0 | 657 | } |
michael@0 | 658 | |
michael@0 | 659 | NS_RELEASE(dialogs); |
michael@0 | 660 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 661 | PK11SlotInfo *used_slot = nullptr; |
michael@0 | 662 | rv = KeygenRunnable->ConsumeResult(&used_slot, &privateKey, &publicKey); |
michael@0 | 663 | if (NS_SUCCEEDED(rv) && used_slot) { |
michael@0 | 664 | PK11_FreeSlot(used_slot); |
michael@0 | 665 | } |
michael@0 | 666 | } |
michael@0 | 667 | } |
michael@0 | 668 | } |
michael@0 | 669 | |
michael@0 | 670 | if (NS_FAILED(rv) || !privateKey) { |
michael@0 | 671 | goto loser; |
michael@0 | 672 | } |
michael@0 | 673 | // just in case we'll need to authenticate to the db -jp // |
michael@0 | 674 | privateKey->wincx = m_ctx; |
michael@0 | 675 | |
michael@0 | 676 | /* |
michael@0 | 677 | * Create a subject public key info from the public key. |
michael@0 | 678 | */ |
michael@0 | 679 | spkInfo = SECKEY_CreateSubjectPublicKeyInfo(publicKey); |
michael@0 | 680 | if ( !spkInfo ) { |
michael@0 | 681 | goto loser; |
michael@0 | 682 | } |
michael@0 | 683 | |
michael@0 | 684 | /* |
michael@0 | 685 | * Now DER encode the whole subjectPublicKeyInfo. |
michael@0 | 686 | */ |
michael@0 | 687 | sec_rv=DER_Encode(arena, &spkiItem, CERTSubjectPublicKeyInfoTemplate, spkInfo); |
michael@0 | 688 | if (sec_rv != SECSuccess) { |
michael@0 | 689 | goto loser; |
michael@0 | 690 | } |
michael@0 | 691 | |
michael@0 | 692 | /* |
michael@0 | 693 | * set up the PublicKeyAndChallenge data structure, then DER encode it |
michael@0 | 694 | */ |
michael@0 | 695 | pkac.spki = spkiItem; |
michael@0 | 696 | pkac.challenge.len = aChallenge.Length(); |
michael@0 | 697 | pkac.challenge.data = (unsigned char *)ToNewCString(aChallenge); |
michael@0 | 698 | if (!pkac.challenge.data) { |
michael@0 | 699 | rv = NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 700 | goto loser; |
michael@0 | 701 | } |
michael@0 | 702 | |
michael@0 | 703 | sec_rv = DER_Encode(arena, &pkacItem, CERTPublicKeyAndChallengeTemplate, &pkac); |
michael@0 | 704 | if ( sec_rv != SECSuccess ) { |
michael@0 | 705 | goto loser; |
michael@0 | 706 | } |
michael@0 | 707 | |
michael@0 | 708 | /* |
michael@0 | 709 | * now sign the DER encoded PublicKeyAndChallenge |
michael@0 | 710 | */ |
michael@0 | 711 | sec_rv = SEC_DerSignData(arena, &signedItem, pkacItem.data, pkacItem.len, |
michael@0 | 712 | privateKey, algTag); |
michael@0 | 713 | if ( sec_rv != SECSuccess ) { |
michael@0 | 714 | goto loser; |
michael@0 | 715 | } |
michael@0 | 716 | |
michael@0 | 717 | /* |
michael@0 | 718 | * Convert the signed public key and challenge into base64/ascii. |
michael@0 | 719 | */ |
michael@0 | 720 | keystring = BTOA_DataToAscii(signedItem.data, signedItem.len); |
michael@0 | 721 | if (!keystring) { |
michael@0 | 722 | rv = NS_ERROR_OUT_OF_MEMORY; |
michael@0 | 723 | goto loser; |
michael@0 | 724 | } |
michael@0 | 725 | |
michael@0 | 726 | CopyASCIItoUTF16(keystring, aOutPublicKey); |
michael@0 | 727 | free(keystring); |
michael@0 | 728 | |
michael@0 | 729 | rv = NS_OK; |
michael@0 | 730 | loser: |
michael@0 | 731 | if ( sec_rv != SECSuccess ) { |
michael@0 | 732 | if ( privateKey ) { |
michael@0 | 733 | PK11_DestroyTokenObject(privateKey->pkcs11Slot,privateKey->pkcs11ID); |
michael@0 | 734 | } |
michael@0 | 735 | if ( publicKey ) { |
michael@0 | 736 | PK11_DestroyTokenObject(publicKey->pkcs11Slot,publicKey->pkcs11ID); |
michael@0 | 737 | } |
michael@0 | 738 | } |
michael@0 | 739 | if ( spkInfo ) { |
michael@0 | 740 | SECKEY_DestroySubjectPublicKeyInfo(spkInfo); |
michael@0 | 741 | } |
michael@0 | 742 | if ( publicKey ) { |
michael@0 | 743 | SECKEY_DestroyPublicKey(publicKey); |
michael@0 | 744 | } |
michael@0 | 745 | if ( privateKey ) { |
michael@0 | 746 | SECKEY_DestroyPrivateKey(privateKey); |
michael@0 | 747 | } |
michael@0 | 748 | if ( arena ) { |
michael@0 | 749 | PORT_FreeArena(arena, true); |
michael@0 | 750 | } |
michael@0 | 751 | if (slot) { |
michael@0 | 752 | PK11_FreeSlot(slot); |
michael@0 | 753 | } |
michael@0 | 754 | if (KeygenRunnable) { |
michael@0 | 755 | NS_RELEASE(KeygenRunnable); |
michael@0 | 756 | } |
michael@0 | 757 | if (keyparamsString) { |
michael@0 | 758 | nsMemory::Free(keyparamsString); |
michael@0 | 759 | } |
michael@0 | 760 | if (pkac.challenge.data) { |
michael@0 | 761 | nsMemory::Free(pkac.challenge.data); |
michael@0 | 762 | } |
michael@0 | 763 | return rv; |
michael@0 | 764 | } |
michael@0 | 765 | |
michael@0 | 766 | NS_METHOD |
michael@0 | 767 | nsKeygenFormProcessor::ProcessValue(nsIDOMHTMLElement *aElement, |
michael@0 | 768 | const nsAString& aName, |
michael@0 | 769 | nsAString& aValue) |
michael@0 | 770 | { |
michael@0 | 771 | nsAutoString challengeValue; |
michael@0 | 772 | nsAutoString keyTypeValue; |
michael@0 | 773 | nsAutoString keyParamsValue; |
michael@0 | 774 | |
michael@0 | 775 | aElement->GetAttribute(NS_LITERAL_STRING("keytype"), keyTypeValue); |
michael@0 | 776 | if (keyTypeValue.IsEmpty()) { |
michael@0 | 777 | // If this field is not present, we default to rsa. |
michael@0 | 778 | keyTypeValue.AssignLiteral("rsa"); |
michael@0 | 779 | } |
michael@0 | 780 | |
michael@0 | 781 | aElement->GetAttribute(NS_LITERAL_STRING("pqg"), |
michael@0 | 782 | keyParamsValue); |
michael@0 | 783 | /* XXX We can still support the pqg attribute in the keygen |
michael@0 | 784 | * tag for backward compatibility while introducing a more |
michael@0 | 785 | * general attribute named keyparams. |
michael@0 | 786 | */ |
michael@0 | 787 | if (keyParamsValue.IsEmpty()) { |
michael@0 | 788 | aElement->GetAttribute(NS_LITERAL_STRING("keyparams"), |
michael@0 | 789 | keyParamsValue); |
michael@0 | 790 | } |
michael@0 | 791 | |
michael@0 | 792 | aElement->GetAttribute(NS_LITERAL_STRING("challenge"), challengeValue); |
michael@0 | 793 | |
michael@0 | 794 | return GetPublicKey(aValue, challengeValue, keyTypeValue, |
michael@0 | 795 | aValue, keyParamsValue); |
michael@0 | 796 | } |
michael@0 | 797 | |
michael@0 | 798 | NS_METHOD nsKeygenFormProcessor::ProvideContent(const nsAString& aFormType, |
michael@0 | 799 | nsTArray<nsString>& aContent, |
michael@0 | 800 | nsAString& aAttribute) |
michael@0 | 801 | { |
michael@0 | 802 | if (Compare(aFormType, NS_LITERAL_STRING("SELECT"), |
michael@0 | 803 | nsCaseInsensitiveStringComparator()) == 0) { |
michael@0 | 804 | |
michael@0 | 805 | for (size_t i = 0; i < number_of_key_size_choices; ++i) { |
michael@0 | 806 | aContent.AppendElement(mSECKeySizeChoiceList[i].name); |
michael@0 | 807 | } |
michael@0 | 808 | aAttribute.AssignLiteral("-mozilla-keygen"); |
michael@0 | 809 | } |
michael@0 | 810 | return NS_OK; |
michael@0 | 811 | } |
michael@0 | 812 |