1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/importer/nss_decryptor_system_nss.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <pk11pub.h> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <pk11sdr.h> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h" 1172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/file_path.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/sys_string_conversions.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/nss_util.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochNSSDecryptor::NSSDecryptor() : is_nss_initialized_(false), db_slot_(NULL) {} 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochNSSDecryptor::~NSSDecryptor() { 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (db_slot_) { 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Deliberately leave the user db open, just in case we need to open more 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // than one, because there's an NSS bug with reopening user dbs. 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // https://bugzilla.mozilla.org/show_bug.cgi?id=506140 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SECMOD_CloseUserDB(db_slot_); 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11_FreeSlot(db_slot_); 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool NSSDecryptor::Init(const FilePath& dll_path, const FilePath& db_path) { 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen crypto::EnsureNSSInit(); 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch is_nss_initialized_ = true; 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string modspec = 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StringPrintf("configDir='%s' tokenDescription='Firefox NSS database' " 3272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "flags=readOnly", db_path.value().c_str()); 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch db_slot_ = SECMOD_OpenUserDB(modspec.c_str()); 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return db_slot_ != NULL; 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This method is based on some NSS code in 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// security/nss/lib/pk11wrap/pk11sdr.c, CVS revision 1.22 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This code is copied because the implementation assumes the use of the 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// internal key slot for decryption, but we need to use another slot. 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The license block is: 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* ***** BEGIN LICENSE BLOCK ***** 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Version: MPL 1.1/GPL 2.0/LGPL 2.1 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * The contents of this file are subject to the Mozilla Public License Version 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 1.1 (the "License"); you may not use this file except in compliance with 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * the License. You may obtain a copy of the License at 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * http://www.mozilla.org/MPL/ 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Software distributed under the License is distributed on an "AS IS" basis, 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * for the specific language governing rights and limitations under the 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * License. 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * The Original Code is the Netscape security libraries. 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * The Initial Developer of the Original Code is 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Netscape Communications Corporation. 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Portions created by the Initial Developer are Copyright (C) 1994-2000 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * the Initial Developer. All Rights Reserved. 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Contributor(s): 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * thayes@netscape.com 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Alternatively, the contents of this file may be used under the terms of 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * either the GNU General Public License Version 2 or later (the "GPL"), or 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * in which case the provisions of the GPL or the LGPL are applicable instead 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * of those above. If you wish to allow use of your version of this file only 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * under the terms of either the GPL or the LGPL, and not to allow others to 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * use your version of this file under the terms of the MPL, indicate your 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * decision by deleting the provisions above and replace them with the notice 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * and other provisions required by the GPL or the LGPL. If you do not delete 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * the provisions above, a recipient may use your version of this file under 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * the terms of any one of the MPL, the GPL or the LGPL. 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * ***** END LICENSE BLOCK ***** */ 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Data structure and template for encoding the result of an SDR operation 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * This is temporary. It should include the algorithm ID of the encryption 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * mechanism 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct SDRResult 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECItem keyid; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECAlgorithmID alg; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECItem data; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef struct SDRResult SDRResult; 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic SEC_ASN1Template g_template[] = { 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (SDRResult) }, 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, keyid) }, 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(SDRResult, alg), 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, data) }, 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 0 } 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic SECStatus 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochunpadBlock(SECItem *data, int blockSize, SECItem *result) 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECStatus rv = SECSuccess; 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int padLength; 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int i; 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->data = 0; 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->len = 0; 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* Remove the padding from the end if the input data */ 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data->len == 0 || data->len % blockSize != 0) { 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = SECFailure; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch goto loser; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch padLength = data->data[data->len-1]; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (padLength > blockSize) { rv = SECFailure; goto loser; } 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* verify padding */ 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (i=data->len - padLength; static_cast<uint32>(i) < data->len; i++) { 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (data->data[i] != padLength) { 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = SECFailure; 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch goto loser; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->len = data->len - padLength; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch result->data = (unsigned char *)PORT_Alloc(result->len); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!result->data) { rv = SECFailure; goto loser; } 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PORT_Memcpy(result->data, data->data, result->len); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (padLength < 2) { 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return SECWouldBlock; 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochloser: 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* decrypt a block */ 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic SECStatus 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochpk11Decrypt(PK11SlotInfo *slot, PLArenaPool *arena, 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CK_MECHANISM_TYPE type, PK11SymKey *key, 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECItem *params, SECItem *in, SECItem *result) 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11Context *ctx = 0; 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECItem paddedResult; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECStatus rv; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paddedResult.len = 0; 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paddedResult.data = 0; 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ctx = PK11_CreateContextBySymKey(type, CKA_DECRYPT, key, params); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ctx) { rv = SECFailure; goto loser; } 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paddedResult.len = in->len; 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch paddedResult.data = static_cast<unsigned char*>( 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PORT_ArenaAlloc(arena, paddedResult.len)); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = PK11_CipherOp(ctx, paddedResult.data, 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (int*)&paddedResult.len, paddedResult.len, 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in->data, in->len); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != SECSuccess) goto loser; 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11_Finalize(ctx); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* Remove the padding */ 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = unpadBlock(&paddedResult, PK11_GetBlockSize(type, 0), result); 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv) goto loser; 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochloser: 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (ctx) PK11_DestroyContext(ctx, PR_TRUE); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSECStatus NSSDecryptor::PK11SDR_DecryptWithSlot( 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11SlotInfo* slot, SECItem* data, SECItem* result, void* cx) const { 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECStatus rv = SECSuccess; 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11SymKey *key = 0; 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CK_MECHANISM_TYPE type; 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SDRResult sdrResult; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECItem *params = 0; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECItem possibleResult = { siBuffer, NULL, 0 }; 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PLArenaPool *arena = 0; 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!arena) { rv = SECFailure; goto loser; } 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* Decode the incoming data */ 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memset(&sdrResult, 0, sizeof sdrResult); 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = SEC_QuickDERDecodeItem(arena, &sdrResult, g_template, data); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != SECSuccess) goto loser; /* Invalid format */ 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* Get the parameter values from the data */ 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch params = PK11_ParamFromAlgid(&sdrResult.alg); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!params) { rv = SECFailure; goto loser; } 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* Use triple-DES (Should look up the algorithm) */ 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch type = CKM_DES3_CBC; 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch key = PK11_FindFixedKey(slot, type, &sdrResult.keyid, cx); 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!key) { 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = SECFailure; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = pk11Decrypt(slot, arena, type, key, params, 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &sdrResult.data, result); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * if the pad value was too small (1 or 2), then it's statistically 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 'likely' that (1 in 256) that we may not have the correct key. 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Check the other keys for a better match. If we find none, use 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * this result. 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv == SECWouldBlock) 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possibleResult = *result; 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * handle the case where your key indicies may have been broken 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch */ 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != SECSuccess) { 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11SymKey *keyList = PK11_ListFixedKeysInSlot(slot, NULL, cx); 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11SymKey *testKey = NULL; 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11SymKey *nextKey = NULL; 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (testKey = keyList; testKey; 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch testKey = PK11_GetNextSymKey(testKey)) { 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = pk11Decrypt(slot, arena, type, testKey, params, 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &sdrResult.data, result); 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv == SECSuccess) 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* found a close match. If it's our first remember it */ 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv == SECWouldBlock) { 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (possibleResult.data) { 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* this is unlikely but possible. If we hit this condition, 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * we have no way of knowing which possibility to prefer. 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * in this case we just match the key the application 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * thought was the right one */ 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECITEM_ZfreeItem(result, PR_FALSE); 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possibleResult = *result; 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* free the list */ 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (testKey = keyList; testKey; testKey = nextKey) { 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nextKey = PK11_GetNextSymKey(testKey); 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PK11_FreeSymKey(testKey); 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch /* we didn't find a better key, use the one with a small pad value */ 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((rv != SECSuccess) && (possibleResult.data)) { 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *result = possibleResult; 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch possibleResult.data = NULL; 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = SECSuccess; 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch loser: 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (arena) PORT_FreeArena(arena, PR_TRUE); 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (key) PK11_FreeSymKey(key); 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (params) SECITEM_ZfreeItem(params, PR_TRUE); 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (possibleResult.data) SECITEM_ZfreeItem(&possibleResult, PR_FALSE); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 270