toolkit/identity/IdentityCryptoService.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
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 file,
michael@0 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "nsIIdentityCryptoService.h"
michael@0 8 #include "mozilla/ModuleUtils.h"
michael@0 9 #include "nsServiceManagerUtils.h"
michael@0 10 #include "nsNSSShutDown.h"
michael@0 11 #include "nsIThread.h"
michael@0 12 #include "nsThreadUtils.h"
michael@0 13 #include "nsCOMPtr.h"
michael@0 14 #include "nsProxyRelease.h"
michael@0 15 #include "nsString.h"
michael@0 16 #include "mozilla/ArrayUtils.h" // ArrayLength
michael@0 17 #include "mozilla/Base64.h"
michael@0 18 #include "ScopedNSSTypes.h"
michael@0 19
michael@0 20 #include "nss.h"
michael@0 21 #include "pk11pub.h"
michael@0 22 #include "secmod.h"
michael@0 23 #include "secerr.h"
michael@0 24 #include "keyhi.h"
michael@0 25 #include "cryptohi.h"
michael@0 26
michael@0 27 #include <limits.h>
michael@0 28
michael@0 29 using namespace mozilla;
michael@0 30
michael@0 31 namespace {
michael@0 32
michael@0 33 void
michael@0 34 HexEncode(const SECItem * it, nsACString & result)
michael@0 35 {
michael@0 36 const char * digits = "0123456789ABCDEF";
michael@0 37 result.SetCapacity((it->len * 2) + 1);
michael@0 38 result.SetLength(it->len * 2);
michael@0 39 char * p = result.BeginWriting();
michael@0 40 for (unsigned int i = 0; i < it->len; ++i) {
michael@0 41 *p++ = digits[it->data[i] >> 4];
michael@0 42 *p++ = digits[it->data[i] & 0x0f];
michael@0 43 }
michael@0 44 }
michael@0 45
michael@0 46 nsresult
michael@0 47 Base64UrlEncodeImpl(const nsACString & utf8Input, nsACString & result)
michael@0 48 {
michael@0 49 nsresult rv = Base64Encode(utf8Input, result);
michael@0 50
michael@0 51 NS_ENSURE_SUCCESS(rv, rv);
michael@0 52
michael@0 53 nsACString::char_type * out = result.BeginWriting();
michael@0 54 nsACString::size_type length = result.Length();
michael@0 55 // base64url encoding is defined in RFC 4648. It replaces the last two
michael@0 56 // alphabet characters of base64 encoding with '-' and '_' respectively.
michael@0 57 for (unsigned int i = 0; i < length; ++i) {
michael@0 58 if (out[i] == '+') {
michael@0 59 out[i] = '-';
michael@0 60 } else if (out[i] == '/') {
michael@0 61 out[i] = '_';
michael@0 62 }
michael@0 63 }
michael@0 64
michael@0 65 return NS_OK;
michael@0 66 }
michael@0 67
michael@0 68 #define DSA_KEY_TYPE_STRING (NS_LITERAL_CSTRING("DS160"))
michael@0 69 #define RSA_KEY_TYPE_STRING (NS_LITERAL_CSTRING("RS256"))
michael@0 70
michael@0 71 class KeyPair : public nsIIdentityKeyPair, public nsNSSShutDownObject
michael@0 72 {
michael@0 73 public:
michael@0 74 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 75 NS_DECL_NSIIDENTITYKEYPAIR
michael@0 76
michael@0 77 KeyPair(SECKEYPrivateKey* aPrivateKey, SECKEYPublicKey* aPublicKey);
michael@0 78
michael@0 79 private:
michael@0 80 ~KeyPair()
michael@0 81 {
michael@0 82 nsNSSShutDownPreventionLock locker;
michael@0 83 if (isAlreadyShutDown()) {
michael@0 84 return;
michael@0 85 }
michael@0 86 destructorSafeDestroyNSSReference();
michael@0 87 shutdown(calledFromObject);
michael@0 88 }
michael@0 89
michael@0 90 void virtualDestroyNSSReference() MOZ_OVERRIDE
michael@0 91 {
michael@0 92 destructorSafeDestroyNSSReference();
michael@0 93 }
michael@0 94
michael@0 95 void destructorSafeDestroyNSSReference()
michael@0 96 {
michael@0 97 SECKEY_DestroyPrivateKey(mPrivateKey);
michael@0 98 mPrivateKey = nullptr;
michael@0 99 SECKEY_DestroyPublicKey(mPublicKey);
michael@0 100 mPublicKey = nullptr;
michael@0 101 }
michael@0 102
michael@0 103 SECKEYPrivateKey * mPrivateKey;
michael@0 104 SECKEYPublicKey * mPublicKey;
michael@0 105
michael@0 106 KeyPair(const KeyPair &) MOZ_DELETE;
michael@0 107 void operator=(const KeyPair &) MOZ_DELETE;
michael@0 108 };
michael@0 109
michael@0 110 NS_IMPL_ISUPPORTS(KeyPair, nsIIdentityKeyPair)
michael@0 111
michael@0 112 class KeyGenRunnable : public nsRunnable, public nsNSSShutDownObject
michael@0 113 {
michael@0 114 public:
michael@0 115 NS_DECL_NSIRUNNABLE
michael@0 116
michael@0 117 KeyGenRunnable(KeyType keyType, nsIIdentityKeyGenCallback * aCallback);
michael@0 118
michael@0 119 private:
michael@0 120 ~KeyGenRunnable()
michael@0 121 {
michael@0 122 nsNSSShutDownPreventionLock locker;
michael@0 123 if (isAlreadyShutDown()) {
michael@0 124 return;
michael@0 125 }
michael@0 126 destructorSafeDestroyNSSReference();
michael@0 127 shutdown(calledFromObject);
michael@0 128 }
michael@0 129
michael@0 130 virtual void virtualDestroyNSSReference() MOZ_OVERRIDE
michael@0 131 {
michael@0 132 destructorSafeDestroyNSSReference();
michael@0 133 }
michael@0 134
michael@0 135 void destructorSafeDestroyNSSReference()
michael@0 136 {
michael@0 137 }
michael@0 138
michael@0 139 const KeyType mKeyType; // in
michael@0 140 nsMainThreadPtrHandle<nsIIdentityKeyGenCallback> mCallback; // in
michael@0 141 nsresult mRv; // out
michael@0 142 nsCOMPtr<nsIIdentityKeyPair> mKeyPair; // out
michael@0 143
michael@0 144 KeyGenRunnable(const KeyGenRunnable &) MOZ_DELETE;
michael@0 145 void operator=(const KeyGenRunnable &) MOZ_DELETE;
michael@0 146 };
michael@0 147
michael@0 148 class SignRunnable : public nsRunnable, public nsNSSShutDownObject
michael@0 149 {
michael@0 150 public:
michael@0 151 NS_DECL_NSIRUNNABLE
michael@0 152
michael@0 153 SignRunnable(const nsACString & textToSign, SECKEYPrivateKey * privateKey,
michael@0 154 nsIIdentitySignCallback * aCallback);
michael@0 155
michael@0 156 private:
michael@0 157 ~SignRunnable()
michael@0 158 {
michael@0 159 nsNSSShutDownPreventionLock locker;
michael@0 160 if (isAlreadyShutDown()) {
michael@0 161 return;
michael@0 162 }
michael@0 163 destructorSafeDestroyNSSReference();
michael@0 164 shutdown(calledFromObject);
michael@0 165 }
michael@0 166
michael@0 167 void virtualDestroyNSSReference() MOZ_OVERRIDE
michael@0 168 {
michael@0 169 destructorSafeDestroyNSSReference();
michael@0 170 }
michael@0 171
michael@0 172 void destructorSafeDestroyNSSReference()
michael@0 173 {
michael@0 174 SECKEY_DestroyPrivateKey(mPrivateKey);
michael@0 175 mPrivateKey = nullptr;
michael@0 176 }
michael@0 177
michael@0 178 const nsCString mTextToSign; // in
michael@0 179 SECKEYPrivateKey* mPrivateKey; // in
michael@0 180 nsMainThreadPtrHandle<nsIIdentitySignCallback> mCallback; // in
michael@0 181 nsresult mRv; // out
michael@0 182 nsCString mSignature; // out
michael@0 183
michael@0 184 private:
michael@0 185 SignRunnable(const SignRunnable &) MOZ_DELETE;
michael@0 186 void operator=(const SignRunnable &) MOZ_DELETE;
michael@0 187 };
michael@0 188
michael@0 189 class IdentityCryptoService MOZ_FINAL : public nsIIdentityCryptoService
michael@0 190 {
michael@0 191 public:
michael@0 192 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 193 NS_DECL_NSIIDENTITYCRYPTOSERVICE
michael@0 194
michael@0 195 IdentityCryptoService() { }
michael@0 196 nsresult Init()
michael@0 197 {
michael@0 198 nsresult rv;
michael@0 199 nsCOMPtr<nsISupports> dummyUsedToEnsureNSSIsInitialized
michael@0 200 = do_GetService("@mozilla.org/psm;1", &rv);
michael@0 201 NS_ENSURE_SUCCESS(rv, rv);
michael@0 202
michael@0 203 return NS_OK;
michael@0 204 }
michael@0 205
michael@0 206 private:
michael@0 207 IdentityCryptoService(const KeyPair &) MOZ_DELETE;
michael@0 208 void operator=(const IdentityCryptoService &) MOZ_DELETE;
michael@0 209 };
michael@0 210
michael@0 211 NS_IMPL_ISUPPORTS(IdentityCryptoService, nsIIdentityCryptoService)
michael@0 212
michael@0 213 NS_IMETHODIMP
michael@0 214 IdentityCryptoService::GenerateKeyPair(
michael@0 215 const nsACString & keyTypeString, nsIIdentityKeyGenCallback * callback)
michael@0 216 {
michael@0 217 KeyType keyType;
michael@0 218 if (keyTypeString.Equals(RSA_KEY_TYPE_STRING)) {
michael@0 219 keyType = rsaKey;
michael@0 220 } else if (keyTypeString.Equals(DSA_KEY_TYPE_STRING)) {
michael@0 221 keyType = dsaKey;
michael@0 222 } else {
michael@0 223 return NS_ERROR_UNEXPECTED;
michael@0 224 }
michael@0 225
michael@0 226 nsCOMPtr<nsIRunnable> r = new KeyGenRunnable(keyType, callback);
michael@0 227 nsCOMPtr<nsIThread> thread;
michael@0 228 nsresult rv = NS_NewThread(getter_AddRefs(thread), r);
michael@0 229 NS_ENSURE_SUCCESS(rv, rv);
michael@0 230
michael@0 231 return NS_OK;
michael@0 232 }
michael@0 233
michael@0 234 NS_IMETHODIMP
michael@0 235 IdentityCryptoService::Base64UrlEncode(const nsACString & utf8Input,
michael@0 236 nsACString & result)
michael@0 237 {
michael@0 238 return Base64UrlEncodeImpl(utf8Input, result);
michael@0 239 }
michael@0 240
michael@0 241 KeyPair::KeyPair(SECKEYPrivateKey * privateKey, SECKEYPublicKey * publicKey)
michael@0 242 : mPrivateKey(privateKey)
michael@0 243 , mPublicKey(publicKey)
michael@0 244 {
michael@0 245 MOZ_ASSERT(!NS_IsMainThread());
michael@0 246 }
michael@0 247
michael@0 248 NS_IMETHODIMP
michael@0 249 KeyPair::GetHexRSAPublicKeyExponent(nsACString & result)
michael@0 250 {
michael@0 251 MOZ_ASSERT(NS_IsMainThread());
michael@0 252 NS_ENSURE_TRUE(mPublicKey, NS_ERROR_NOT_AVAILABLE);
michael@0 253 NS_ENSURE_TRUE(mPublicKey->keyType == rsaKey, NS_ERROR_NOT_AVAILABLE);
michael@0 254 HexEncode(&mPublicKey->u.rsa.publicExponent, result);
michael@0 255 return NS_OK;
michael@0 256 }
michael@0 257
michael@0 258 NS_IMETHODIMP
michael@0 259 KeyPair::GetHexRSAPublicKeyModulus(nsACString & result)
michael@0 260 {
michael@0 261 MOZ_ASSERT(NS_IsMainThread());
michael@0 262 NS_ENSURE_TRUE(mPublicKey, NS_ERROR_NOT_AVAILABLE);
michael@0 263 NS_ENSURE_TRUE(mPublicKey->keyType == rsaKey, NS_ERROR_NOT_AVAILABLE);
michael@0 264 HexEncode(&mPublicKey->u.rsa.modulus, result);
michael@0 265 return NS_OK;
michael@0 266 }
michael@0 267
michael@0 268 NS_IMETHODIMP
michael@0 269 KeyPair::GetHexDSAPrime(nsACString & result)
michael@0 270 {
michael@0 271 MOZ_ASSERT(NS_IsMainThread());
michael@0 272 NS_ENSURE_TRUE(mPublicKey, NS_ERROR_NOT_AVAILABLE);
michael@0 273 NS_ENSURE_TRUE(mPublicKey->keyType == dsaKey, NS_ERROR_NOT_AVAILABLE);
michael@0 274 HexEncode(&mPublicKey->u.dsa.params.prime, result);
michael@0 275 return NS_OK;
michael@0 276 }
michael@0 277
michael@0 278 NS_IMETHODIMP
michael@0 279 KeyPair::GetHexDSASubPrime(nsACString & result)
michael@0 280 {
michael@0 281 MOZ_ASSERT(NS_IsMainThread());
michael@0 282 NS_ENSURE_TRUE(mPublicKey, NS_ERROR_NOT_AVAILABLE);
michael@0 283 NS_ENSURE_TRUE(mPublicKey->keyType == dsaKey, NS_ERROR_NOT_AVAILABLE);
michael@0 284 HexEncode(&mPublicKey->u.dsa.params.subPrime, result);
michael@0 285 return NS_OK;
michael@0 286 }
michael@0 287
michael@0 288 NS_IMETHODIMP
michael@0 289 KeyPair::GetHexDSAGenerator(nsACString & result)
michael@0 290 {
michael@0 291 MOZ_ASSERT(NS_IsMainThread());
michael@0 292 NS_ENSURE_TRUE(mPublicKey, NS_ERROR_NOT_AVAILABLE);
michael@0 293 NS_ENSURE_TRUE(mPublicKey->keyType == dsaKey, NS_ERROR_NOT_AVAILABLE);
michael@0 294 HexEncode(&mPublicKey->u.dsa.params.base, result);
michael@0 295 return NS_OK;
michael@0 296 }
michael@0 297
michael@0 298 NS_IMETHODIMP
michael@0 299 KeyPair::GetHexDSAPublicValue(nsACString & result)
michael@0 300 {
michael@0 301 MOZ_ASSERT(NS_IsMainThread());
michael@0 302 NS_ENSURE_TRUE(mPublicKey, NS_ERROR_NOT_AVAILABLE);
michael@0 303 NS_ENSURE_TRUE(mPublicKey->keyType == dsaKey, NS_ERROR_NOT_AVAILABLE);
michael@0 304 HexEncode(&mPublicKey->u.dsa.publicValue, result);
michael@0 305 return NS_OK;
michael@0 306 }
michael@0 307
michael@0 308 NS_IMETHODIMP
michael@0 309 KeyPair::GetKeyType(nsACString & result)
michael@0 310 {
michael@0 311 MOZ_ASSERT(NS_IsMainThread());
michael@0 312 NS_ENSURE_TRUE(mPublicKey, NS_ERROR_NOT_AVAILABLE);
michael@0 313
michael@0 314 switch (mPublicKey->keyType) {
michael@0 315 case rsaKey: result = RSA_KEY_TYPE_STRING; return NS_OK;
michael@0 316 case dsaKey: result = DSA_KEY_TYPE_STRING; return NS_OK;
michael@0 317 default: return NS_ERROR_UNEXPECTED;
michael@0 318 }
michael@0 319 }
michael@0 320
michael@0 321 NS_IMETHODIMP
michael@0 322 KeyPair::Sign(const nsACString & textToSign,
michael@0 323 nsIIdentitySignCallback* callback)
michael@0 324 {
michael@0 325 MOZ_ASSERT(NS_IsMainThread());
michael@0 326 nsCOMPtr<nsIRunnable> r = new SignRunnable(textToSign, mPrivateKey,
michael@0 327 callback);
michael@0 328
michael@0 329 nsCOMPtr<nsIThread> thread;
michael@0 330 nsresult rv = NS_NewThread(getter_AddRefs(thread), r);
michael@0 331 return rv;
michael@0 332 }
michael@0 333
michael@0 334 KeyGenRunnable::KeyGenRunnable(KeyType keyType,
michael@0 335 nsIIdentityKeyGenCallback * callback)
michael@0 336 : mKeyType(keyType)
michael@0 337 , mCallback(new nsMainThreadPtrHolder<nsIIdentityKeyGenCallback>(callback))
michael@0 338 , mRv(NS_ERROR_NOT_INITIALIZED)
michael@0 339 {
michael@0 340 }
michael@0 341
michael@0 342 MOZ_WARN_UNUSED_RESULT nsresult
michael@0 343 GenerateKeyPair(PK11SlotInfo * slot,
michael@0 344 SECKEYPrivateKey ** privateKey,
michael@0 345 SECKEYPublicKey ** publicKey,
michael@0 346 CK_MECHANISM_TYPE mechanism,
michael@0 347 void * params)
michael@0 348 {
michael@0 349 *publicKey = nullptr;
michael@0 350 *privateKey = PK11_GenerateKeyPair(slot, mechanism, params, publicKey,
michael@0 351 PR_FALSE /*isPerm*/,
michael@0 352 PR_TRUE /*isSensitive*/,
michael@0 353 nullptr /*&pwdata*/);
michael@0 354 if (!*privateKey) {
michael@0 355 MOZ_ASSERT(!*publicKey);
michael@0 356 return PRErrorCode_to_nsresult(PR_GetError());
michael@0 357 }
michael@0 358 if (!*publicKey) {
michael@0 359 SECKEY_DestroyPrivateKey(*privateKey);
michael@0 360 *privateKey = nullptr;
michael@0 361 MOZ_CRASH("PK11_GnerateKeyPair returned private key without public key");
michael@0 362 }
michael@0 363
michael@0 364 return NS_OK;
michael@0 365 }
michael@0 366
michael@0 367
michael@0 368 MOZ_WARN_UNUSED_RESULT nsresult
michael@0 369 GenerateRSAKeyPair(PK11SlotInfo * slot,
michael@0 370 SECKEYPrivateKey ** privateKey,
michael@0 371 SECKEYPublicKey ** publicKey)
michael@0 372 {
michael@0 373 MOZ_ASSERT(!NS_IsMainThread());
michael@0 374
michael@0 375 PK11RSAGenParams rsaParams;
michael@0 376 rsaParams.keySizeInBits = 2048;
michael@0 377 rsaParams.pe = 0x10001;
michael@0 378 return GenerateKeyPair(slot, privateKey, publicKey, CKM_RSA_PKCS_KEY_PAIR_GEN,
michael@0 379 &rsaParams);
michael@0 380 }
michael@0 381
michael@0 382 MOZ_WARN_UNUSED_RESULT nsresult
michael@0 383 GenerateDSAKeyPair(PK11SlotInfo * slot,
michael@0 384 SECKEYPrivateKey ** privateKey,
michael@0 385 SECKEYPublicKey ** publicKey)
michael@0 386 {
michael@0 387 MOZ_ASSERT(!NS_IsMainThread());
michael@0 388
michael@0 389 // XXX: These could probably be static const arrays, but this way we avoid
michael@0 390 // compiler warnings and also we avoid having to worry much about whether the
michael@0 391 // functions that take these inputs will (unexpectedly) modify them.
michael@0 392
michael@0 393 // Using NIST parameters. Some other BrowserID components require that these
michael@0 394 // exact parameters are used.
michael@0 395 uint8_t P[] = {
michael@0 396 0xFF,0x60,0x04,0x83,0xDB,0x6A,0xBF,0xC5,0xB4,0x5E,0xAB,0x78,
michael@0 397 0x59,0x4B,0x35,0x33,0xD5,0x50,0xD9,0xF1,0xBF,0x2A,0x99,0x2A,
michael@0 398 0x7A,0x8D,0xAA,0x6D,0xC3,0x4F,0x80,0x45,0xAD,0x4E,0x6E,0x0C,
michael@0 399 0x42,0x9D,0x33,0x4E,0xEE,0xAA,0xEF,0xD7,0xE2,0x3D,0x48,0x10,
michael@0 400 0xBE,0x00,0xE4,0xCC,0x14,0x92,0xCB,0xA3,0x25,0xBA,0x81,0xFF,
michael@0 401 0x2D,0x5A,0x5B,0x30,0x5A,0x8D,0x17,0xEB,0x3B,0xF4,0xA0,0x6A,
michael@0 402 0x34,0x9D,0x39,0x2E,0x00,0xD3,0x29,0x74,0x4A,0x51,0x79,0x38,
michael@0 403 0x03,0x44,0xE8,0x2A,0x18,0xC4,0x79,0x33,0x43,0x8F,0x89,0x1E,
michael@0 404 0x22,0xAE,0xEF,0x81,0x2D,0x69,0xC8,0xF7,0x5E,0x32,0x6C,0xB7,
michael@0 405 0x0E,0xA0,0x00,0xC3,0xF7,0x76,0xDF,0xDB,0xD6,0x04,0x63,0x8C,
michael@0 406 0x2E,0xF7,0x17,0xFC,0x26,0xD0,0x2E,0x17
michael@0 407 };
michael@0 408
michael@0 409 uint8_t Q[] = {
michael@0 410 0xE2,0x1E,0x04,0xF9,0x11,0xD1,0xED,0x79,0x91,0x00,0x8E,0xCA,
michael@0 411 0xAB,0x3B,0xF7,0x75,0x98,0x43,0x09,0xC3
michael@0 412 };
michael@0 413
michael@0 414 uint8_t G[] = {
michael@0 415 0xC5,0x2A,0x4A,0x0F,0xF3,0xB7,0xE6,0x1F,0xDF,0x18,0x67,0xCE,
michael@0 416 0x84,0x13,0x83,0x69,0xA6,0x15,0x4F,0x4A,0xFA,0x92,0x96,0x6E,
michael@0 417 0x3C,0x82,0x7E,0x25,0xCF,0xA6,0xCF,0x50,0x8B,0x90,0xE5,0xDE,
michael@0 418 0x41,0x9E,0x13,0x37,0xE0,0x7A,0x2E,0x9E,0x2A,0x3C,0xD5,0xDE,
michael@0 419 0xA7,0x04,0xD1,0x75,0xF8,0xEB,0xF6,0xAF,0x39,0x7D,0x69,0xE1,
michael@0 420 0x10,0xB9,0x6A,0xFB,0x17,0xC7,0xA0,0x32,0x59,0x32,0x9E,0x48,
michael@0 421 0x29,0xB0,0xD0,0x3B,0xBC,0x78,0x96,0xB1,0x5B,0x4A,0xDE,0x53,
michael@0 422 0xE1,0x30,0x85,0x8C,0xC3,0x4D,0x96,0x26,0x9A,0xA8,0x90,0x41,
michael@0 423 0xF4,0x09,0x13,0x6C,0x72,0x42,0xA3,0x88,0x95,0xC9,0xD5,0xBC,
michael@0 424 0xCA,0xD4,0xF3,0x89,0xAF,0x1D,0x7A,0x4B,0xD1,0x39,0x8B,0xD0,
michael@0 425 0x72,0xDF,0xFA,0x89,0x62,0x33,0x39,0x7A
michael@0 426 };
michael@0 427
michael@0 428 static_assert(MOZ_ARRAY_LENGTH(P) == 1024 / CHAR_BIT, "bad DSA P");
michael@0 429 static_assert(MOZ_ARRAY_LENGTH(Q) == 160 / CHAR_BIT, "bad DSA Q");
michael@0 430 static_assert(MOZ_ARRAY_LENGTH(G) == 1024 / CHAR_BIT, "bad DSA G");
michael@0 431
michael@0 432 PQGParams pqgParams = {
michael@0 433 nullptr /*arena*/,
michael@0 434 { siBuffer, P, static_cast<unsigned int>(mozilla::ArrayLength(P)) },
michael@0 435 { siBuffer, Q, static_cast<unsigned int>(mozilla::ArrayLength(Q)) },
michael@0 436 { siBuffer, G, static_cast<unsigned int>(mozilla::ArrayLength(G)) }
michael@0 437 };
michael@0 438
michael@0 439 return GenerateKeyPair(slot, privateKey, publicKey, CKM_DSA_KEY_PAIR_GEN,
michael@0 440 &pqgParams);
michael@0 441 }
michael@0 442
michael@0 443 NS_IMETHODIMP
michael@0 444 KeyGenRunnable::Run()
michael@0 445 {
michael@0 446 if (!NS_IsMainThread()) {
michael@0 447 nsNSSShutDownPreventionLock locker;
michael@0 448 if (isAlreadyShutDown()) {
michael@0 449 mRv = NS_ERROR_NOT_AVAILABLE;
michael@0 450 } else {
michael@0 451 // We always want to use the internal slot for BrowserID; in particular,
michael@0 452 // we want to avoid smartcard slots.
michael@0 453 PK11SlotInfo *slot = PK11_GetInternalSlot();
michael@0 454 if (!slot) {
michael@0 455 mRv = NS_ERROR_UNEXPECTED;
michael@0 456 } else {
michael@0 457 SECKEYPrivateKey *privk = nullptr;
michael@0 458 SECKEYPublicKey *pubk = nullptr;
michael@0 459
michael@0 460 switch (mKeyType) {
michael@0 461 case rsaKey:
michael@0 462 mRv = GenerateRSAKeyPair(slot, &privk, &pubk);
michael@0 463 break;
michael@0 464 case dsaKey:
michael@0 465 mRv = GenerateDSAKeyPair(slot, &privk, &pubk);
michael@0 466 break;
michael@0 467 default:
michael@0 468 MOZ_CRASH("unknown key type");
michael@0 469 }
michael@0 470
michael@0 471 PK11_FreeSlot(slot);
michael@0 472
michael@0 473 if (NS_SUCCEEDED(mRv)) {
michael@0 474 MOZ_ASSERT(privk);
michael@0 475 MOZ_ASSERT(pubk);
michael@0 476 // mKeyPair will take over ownership of privk and pubk
michael@0 477 mKeyPair = new KeyPair(privk, pubk);
michael@0 478 }
michael@0 479 }
michael@0 480 }
michael@0 481
michael@0 482 NS_DispatchToMainThread(this);
michael@0 483 } else {
michael@0 484 // Back on Main Thread
michael@0 485 (void) mCallback->GenerateKeyPairFinished(mRv, mKeyPair);
michael@0 486 }
michael@0 487 return NS_OK;
michael@0 488 }
michael@0 489
michael@0 490 SignRunnable::SignRunnable(const nsACString & aText,
michael@0 491 SECKEYPrivateKey * privateKey,
michael@0 492 nsIIdentitySignCallback * aCallback)
michael@0 493 : mTextToSign(aText)
michael@0 494 , mPrivateKey(SECKEY_CopyPrivateKey(privateKey))
michael@0 495 , mCallback(new nsMainThreadPtrHolder<nsIIdentitySignCallback>(aCallback))
michael@0 496 , mRv(NS_ERROR_NOT_INITIALIZED)
michael@0 497 {
michael@0 498 }
michael@0 499
michael@0 500 NS_IMETHODIMP
michael@0 501 SignRunnable::Run()
michael@0 502 {
michael@0 503 if (!NS_IsMainThread()) {
michael@0 504 nsNSSShutDownPreventionLock locker;
michael@0 505 if (isAlreadyShutDown()) {
michael@0 506 mRv = NS_ERROR_NOT_AVAILABLE;
michael@0 507 } else {
michael@0 508 // We need the output in PKCS#11 format, not DER encoding, so we must use
michael@0 509 // PK11_HashBuf and PK11_Sign instead of SEC_SignData.
michael@0 510
michael@0 511 SECItem sig = { siBuffer, nullptr, 0 };
michael@0 512 int sigLength = PK11_SignatureLen(mPrivateKey);
michael@0 513 if (sigLength <= 0) {
michael@0 514 mRv = PRErrorCode_to_nsresult(PR_GetError());
michael@0 515 } else if (!SECITEM_AllocItem(nullptr, &sig, sigLength)) {
michael@0 516 mRv = PRErrorCode_to_nsresult(PR_GetError());
michael@0 517 } else {
michael@0 518 uint8_t hash[32]; // big enough for SHA-1 or SHA-256
michael@0 519 SECOidTag hashAlg = mPrivateKey->keyType == dsaKey ? SEC_OID_SHA1
michael@0 520 : SEC_OID_SHA256;
michael@0 521 SECItem hashItem = { siBuffer, hash,
michael@0 522 hashAlg == SEC_OID_SHA1 ? 20u : 32u };
michael@0 523
michael@0 524 mRv = MapSECStatus(PK11_HashBuf(hashAlg, hash,
michael@0 525 const_cast<uint8_t*>(reinterpret_cast<const uint8_t *>(
michael@0 526 mTextToSign.get())),
michael@0 527 mTextToSign.Length()));
michael@0 528 if (NS_SUCCEEDED(mRv)) {
michael@0 529 mRv = MapSECStatus(PK11_Sign(mPrivateKey, &sig, &hashItem));
michael@0 530 }
michael@0 531 if (NS_SUCCEEDED(mRv)) {
michael@0 532 nsDependentCSubstring sigString(
michael@0 533 reinterpret_cast<const char*>(sig.data), sig.len);
michael@0 534 mRv = Base64UrlEncodeImpl(sigString, mSignature);
michael@0 535 }
michael@0 536 SECITEM_FreeItem(&sig, false);
michael@0 537 }
michael@0 538 }
michael@0 539
michael@0 540 NS_DispatchToMainThread(this);
michael@0 541 } else {
michael@0 542 // Back on Main Thread
michael@0 543 (void) mCallback->SignFinished(mRv, mSignature);
michael@0 544 }
michael@0 545
michael@0 546 return NS_OK;
michael@0 547 }
michael@0 548
michael@0 549 // XPCOM module registration
michael@0 550
michael@0 551 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(IdentityCryptoService, Init)
michael@0 552
michael@0 553 #define NS_IDENTITYCRYPTOSERVICE_CID \
michael@0 554 {0xbea13a3a, 0x44e8, 0x4d7f, {0xa0, 0xa2, 0x2c, 0x67, 0xf8, 0x4e, 0x3a, 0x97}}
michael@0 555
michael@0 556 NS_DEFINE_NAMED_CID(NS_IDENTITYCRYPTOSERVICE_CID);
michael@0 557
michael@0 558 const mozilla::Module::CIDEntry kCIDs[] = {
michael@0 559 { &kNS_IDENTITYCRYPTOSERVICE_CID, false, nullptr, IdentityCryptoServiceConstructor },
michael@0 560 { nullptr }
michael@0 561 };
michael@0 562
michael@0 563 const mozilla::Module::ContractIDEntry kContracts[] = {
michael@0 564 { "@mozilla.org/identity/crypto-service;1", &kNS_IDENTITYCRYPTOSERVICE_CID },
michael@0 565 { nullptr }
michael@0 566 };
michael@0 567
michael@0 568 const mozilla::Module kModule = {
michael@0 569 mozilla::Module::kVersion,
michael@0 570 kCIDs,
michael@0 571 kContracts
michael@0 572 };
michael@0 573
michael@0 574 } // unnamed namespace
michael@0 575
michael@0 576 NSMODULE_DEFN(identity) = &kModule;

mercurial