// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/http/des.h"

#include "base/logging.h"

#if defined(USE_OPENSSL)
#include <openssl/des.h>
#include "crypto/openssl_util.h"
#elif defined(USE_NSS)
#include <nss.h>
#include <pk11pub.h>
#include "crypto/nss_util.h"
#elif defined(OS_MACOSX)
#include <CommonCrypto/CommonCryptor.h>
#elif defined(OS_WIN)
#include <windows.h>
#include <wincrypt.h>
#include "crypto/scoped_capi_types.h"
#endif

// The Mac and Windows (CryptoAPI) versions of DESEncrypt are our own code.
// DESSetKeyParity, DESMakeKey, and the Linux (NSS) version of DESEncrypt are
// based on mozilla/security/manager/ssl/src/nsNTLMAuthModule.cpp,
// CVS rev. 1.14.

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla.
 *
 * The Initial Developer of the Original Code is IBM Corporation.
 * Portions created by IBM Corporation are Copyright (C) 2003
 * IBM Corporation. All Rights Reserved.
 *
 * Contributor(s):
 *   Darin Fisher <darin@meer.net>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

// Set odd parity bit (in least significant bit position).
static uint8 DESSetKeyParity(uint8 x) {
  if ((((x >> 7) ^ (x >> 6) ^ (x >> 5) ^
        (x >> 4) ^ (x >> 3) ^ (x >> 2) ^
        (x >> 1)) & 0x01) == 0) {
    x |= 0x01;
  } else {
    x &= 0xfe;
  }
  return x;
}

namespace net {

void DESMakeKey(const uint8* raw, uint8* key) {
  key[0] = DESSetKeyParity(raw[0]);
  key[1] = DESSetKeyParity((raw[0] << 7) | (raw[1] >> 1));
  key[2] = DESSetKeyParity((raw[1] << 6) | (raw[2] >> 2));
  key[3] = DESSetKeyParity((raw[2] << 5) | (raw[3] >> 3));
  key[4] = DESSetKeyParity((raw[3] << 4) | (raw[4] >> 4));
  key[5] = DESSetKeyParity((raw[4] << 3) | (raw[5] >> 5));
  key[6] = DESSetKeyParity((raw[5] << 2) | (raw[6] >> 6));
  key[7] = DESSetKeyParity((raw[6] << 1));
}

#if defined(USE_OPENSSL)

void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) {
  crypto::EnsureOpenSSLInit();

  DES_key_schedule ks;
  DES_set_key(
      reinterpret_cast<const DES_cblock*>(key), &ks);

  DES_ecb_encrypt(reinterpret_cast<const DES_cblock*>(src),
                  reinterpret_cast<DES_cblock*>(hash), &ks, DES_ENCRYPT);
}

#elif defined(USE_NSS)

void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) {
  CK_MECHANISM_TYPE cipher_mech = CKM_DES_ECB;
  PK11SlotInfo* slot = NULL;
  PK11SymKey* symkey = NULL;
  PK11Context* ctxt = NULL;
  SECItem key_item;
  SECItem* param = NULL;
  SECStatus rv;
  unsigned int n;

  crypto::EnsureNSSInit();

  slot = PK11_GetInternalSlot();
  if (!slot)
    goto done;

  key_item.data = const_cast<uint8*>(key);
  key_item.len = 8;
  symkey = PK11_ImportSymKey(slot, cipher_mech,
                             PK11_OriginUnwrap, CKA_ENCRYPT,
                             &key_item, NULL);
  if (!symkey)
    goto done;

  // No initialization vector required.
  param = PK11_ParamFromIV(cipher_mech, NULL);
  if (!param)
    goto done;

  ctxt = PK11_CreateContextBySymKey(cipher_mech, CKA_ENCRYPT,
                                    symkey, param);
  if (!ctxt)
    goto done;

  rv = PK11_CipherOp(ctxt, hash, reinterpret_cast<int*>(&n), 8,
                     const_cast<uint8*>(src), 8);
  if (rv != SECSuccess)
    goto done;

  // TODO(wtc): Should this be PK11_Finalize?
  rv = PK11_DigestFinal(ctxt, hash+8, &n, 0);
  if (rv != SECSuccess)
    goto done;

 done:
  if (ctxt)
    PK11_DestroyContext(ctxt, PR_TRUE);
  if (symkey)
    PK11_FreeSymKey(symkey);
  if (param)
    SECITEM_FreeItem(param, PR_TRUE);
  if (slot)
    PK11_FreeSlot(slot);
}

#elif defined(OS_MACOSX)

void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) {
  CCCryptorStatus status;
  size_t data_out_moved = 0;
  status = CCCrypt(kCCEncrypt, kCCAlgorithmDES, kCCOptionECBMode,
                   key, 8, NULL, src, 8, hash, 8, &data_out_moved);
  DCHECK(status == kCCSuccess);
  DCHECK(data_out_moved == 8);
}

#elif defined(OS_WIN)

void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) {
  crypto::ScopedHCRYPTPROV provider;
  if (!CryptAcquireContext(provider.receive(), NULL, NULL, PROV_RSA_FULL,
                           CRYPT_VERIFYCONTEXT))
    return;

  {
    // Import the DES key.
    struct KeyBlob {
      BLOBHEADER header;
      DWORD key_size;
      BYTE key_data[8];
    };
    KeyBlob key_blob;
    key_blob.header.bType = PLAINTEXTKEYBLOB;
    key_blob.header.bVersion = CUR_BLOB_VERSION;
    key_blob.header.reserved = 0;
    key_blob.header.aiKeyAlg = CALG_DES;
    key_blob.key_size = 8;  // 64 bits
    memcpy(key_blob.key_data, key, 8);

    crypto::ScopedHCRYPTKEY key;
    BOOL import_ok = CryptImportKey(provider,
                                    reinterpret_cast<BYTE*>(&key_blob),
                                    sizeof key_blob, 0, 0, key.receive());
    // Destroy the copy of the key.
    SecureZeroMemory(key_blob.key_data, sizeof key_blob.key_data);
    if (!import_ok)
      return;

    // No initialization vector required.
    DWORD cipher_mode = CRYPT_MODE_ECB;
    if (!CryptSetKeyParam(key, KP_MODE, reinterpret_cast<BYTE*>(&cipher_mode),
                          0))
      return;

    // CryptoAPI requires us to copy the plaintext to the output buffer first.
    CopyMemory(hash, src, 8);
    // Pass a 'Final' of FALSE, otherwise CryptEncrypt appends one additional
    // block of padding to the data.
    DWORD hash_len = 8;
    CryptEncrypt(key, 0, FALSE, 0, hash, &hash_len, 8);
  }
}

#endif

}  // namespace net
