des.cc revision e00741fe4b5b3d04d95b48b19d56c94fc9bc0237
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/http/des.h" 6 7#include "base/logging.h" 8 9#if defined(USE_NSS) 10#include <nss.h> 11#include <pk11pub.h> 12#include "base/nss_util.h" 13#elif defined(USE_OPENSSL) 14#include <openssl/des.h> 15#elif defined(OS_MACOSX) 16#include <CommonCrypto/CommonCryptor.h> 17#elif defined(OS_WIN) 18#include <windows.h> 19#include <wincrypt.h> 20#include "base/crypto/scoped_capi_types.h" 21#endif 22 23// The Mac and Windows (CryptoAPI) versions of DESEncrypt are our own code. 24// DESSetKeyParity, DESMakeKey, and the Linux (NSS) version of DESEncrypt are 25// based on mozilla/security/manager/ssl/src/nsNTLMAuthModule.cpp, 26// CVS rev. 1.14. 27 28/* ***** BEGIN LICENSE BLOCK ***** 29 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 30 * 31 * The contents of this file are subject to the Mozilla Public License Version 32 * 1.1 (the "License"); you may not use this file except in compliance with 33 * the License. You may obtain a copy of the License at 34 * http://www.mozilla.org/MPL/ 35 * 36 * Software distributed under the License is distributed on an "AS IS" basis, 37 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 38 * for the specific language governing rights and limitations under the 39 * License. 40 * 41 * The Original Code is Mozilla. 42 * 43 * The Initial Developer of the Original Code is IBM Corporation. 44 * Portions created by IBM Corporation are Copyright (C) 2003 45 * IBM Corporation. All Rights Reserved. 46 * 47 * Contributor(s): 48 * Darin Fisher <darin@meer.net> 49 * 50 * Alternatively, the contents of this file may be used under the terms of 51 * either the GNU General Public License Version 2 or later (the "GPL"), or 52 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 53 * in which case the provisions of the GPL or the LGPL are applicable instead 54 * of those above. If you wish to allow use of your version of this file only 55 * under the terms of either the GPL or the LGPL, and not to allow others to 56 * use your version of this file under the terms of the MPL, indicate your 57 * decision by deleting the provisions above and replace them with the notice 58 * and other provisions required by the GPL or the LGPL. If you do not delete 59 * the provisions above, a recipient may use your version of this file under 60 * the terms of any one of the MPL, the GPL or the LGPL. 61 * 62 * ***** END LICENSE BLOCK ***** */ 63 64// Set odd parity bit (in least significant bit position). 65static uint8 DESSetKeyParity(uint8 x) { 66 if ((((x >> 7) ^ (x >> 6) ^ (x >> 5) ^ 67 (x >> 4) ^ (x >> 3) ^ (x >> 2) ^ 68 (x >> 1)) & 0x01) == 0) { 69 x |= 0x01; 70 } else { 71 x &= 0xfe; 72 } 73 return x; 74} 75 76namespace net { 77 78void DESMakeKey(const uint8* raw, uint8* key) { 79 key[0] = DESSetKeyParity(raw[0]); 80 key[1] = DESSetKeyParity((raw[0] << 7) | (raw[1] >> 1)); 81 key[2] = DESSetKeyParity((raw[1] << 6) | (raw[2] >> 2)); 82 key[3] = DESSetKeyParity((raw[2] << 5) | (raw[3] >> 3)); 83 key[4] = DESSetKeyParity((raw[3] << 4) | (raw[4] >> 4)); 84 key[5] = DESSetKeyParity((raw[4] << 3) | (raw[5] >> 5)); 85 key[6] = DESSetKeyParity((raw[5] << 2) | (raw[6] >> 6)); 86 key[7] = DESSetKeyParity((raw[6] << 1)); 87} 88 89#if defined(USE_OPENSSL) 90 91void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { 92 DES_cblock des_key; 93 DES_key_schedule schedule; 94 95 memcpy(des_key, key, 8); 96 DES_set_odd_parity(&des_key); 97 DES_set_key_checked(&des_key, &schedule); 98 99 DES_ecb_encrypt((C_Block *)src, (C_Block *)hash, &schedule, DES_ENCRYPT); 100} 101 102#elif defined(USE_NSS) 103 104void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { 105 CK_MECHANISM_TYPE cipher_mech = CKM_DES_ECB; 106 PK11SlotInfo* slot = NULL; 107 PK11SymKey* symkey = NULL; 108 PK11Context* ctxt = NULL; 109 SECItem key_item; 110 SECItem* param = NULL; 111 SECStatus rv; 112 unsigned int n; 113 114 base::EnsureNSSInit(); 115 116 slot = PK11_GetBestSlot(cipher_mech, NULL); 117 if (!slot) 118 goto done; 119 120 key_item.data = const_cast<uint8*>(key); 121 key_item.len = 8; 122 symkey = PK11_ImportSymKey(slot, cipher_mech, 123 PK11_OriginUnwrap, CKA_ENCRYPT, 124 &key_item, NULL); 125 if (!symkey) 126 goto done; 127 128 // No initialization vector required. 129 param = PK11_ParamFromIV(cipher_mech, NULL); 130 if (!param) 131 goto done; 132 133 ctxt = PK11_CreateContextBySymKey(cipher_mech, CKA_ENCRYPT, 134 symkey, param); 135 if (!ctxt) 136 goto done; 137 138 rv = PK11_CipherOp(ctxt, hash, reinterpret_cast<int*>(&n), 8, 139 const_cast<uint8*>(src), 8); 140 if (rv != SECSuccess) 141 goto done; 142 143 // TODO(wtc): Should this be PK11_Finalize? 144 rv = PK11_DigestFinal(ctxt, hash+8, &n, 0); 145 if (rv != SECSuccess) 146 goto done; 147 148 done: 149 if (ctxt) 150 PK11_DestroyContext(ctxt, PR_TRUE); 151 if (symkey) 152 PK11_FreeSymKey(symkey); 153 if (param) 154 SECITEM_FreeItem(param, PR_TRUE); 155 if (slot) 156 PK11_FreeSlot(slot); 157} 158 159#elif defined(OS_MACOSX) 160 161void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { 162 CCCryptorStatus status; 163 size_t data_out_moved = 0; 164 status = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode, 165 key, 8, NULL, src, 8, hash, 8, &data_out_moved); 166 DCHECK(status == kCCSuccess); 167 DCHECK(data_out_moved == 8); 168} 169 170#elif defined(OS_WIN) 171 172void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { 173 base::ScopedHCRYPTPROV provider; 174 if (!CryptAcquireContext(provider.receive(), NULL, NULL, PROV_RSA_FULL, 175 CRYPT_VERIFYCONTEXT)) 176 return; 177 178 { 179 // Import the DES key. 180 struct KeyBlob { 181 BLOBHEADER header; 182 DWORD key_size; 183 BYTE key_data[8]; 184 }; 185 KeyBlob key_blob; 186 key_blob.header.bType = PLAINTEXTKEYBLOB; 187 key_blob.header.bVersion = CUR_BLOB_VERSION; 188 key_blob.header.reserved = 0; 189 key_blob.header.aiKeyAlg = CALG_DES; 190 key_blob.key_size = 8; // 64 bits 191 memcpy(key_blob.key_data, key, 8); 192 193 base::ScopedHCRYPTKEY key; 194 BOOL import_ok = CryptImportKey(provider, 195 reinterpret_cast<BYTE*>(&key_blob), 196 sizeof key_blob, 0, 0, key.receive()); 197 // Destroy the copy of the key. 198 SecureZeroMemory(key_blob.key_data, sizeof key_blob.key_data); 199 if (!import_ok) 200 return; 201 202 // No initialization vector required. 203 DWORD cipher_mode = CRYPT_MODE_ECB; 204 if (!CryptSetKeyParam(key, KP_MODE, reinterpret_cast<BYTE*>(&cipher_mode), 205 0)) 206 return; 207 208 // CryptoAPI requires us to copy the plaintext to the output buffer first. 209 CopyMemory(hash, src, 8); 210 // Pass a 'Final' of FALSE, otherwise CryptEncrypt appends one additional 211 // block of padding to the data. 212 DWORD hash_len = 8; 213 CryptEncrypt(key, 0, FALSE, 0, hash, &hash_len, 8); 214 } 215} 216 217#endif 218 219} // namespace net 220