• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "crypto/encryptor.h"
6 
7 #include <cryptohi.h>
8 #include <vector>
9 
10 #include "base/logging.h"
11 #include "crypto/nss_util.h"
12 #include "crypto/symmetric_key.h"
13 
14 namespace crypto {
15 
Encryptor()16 Encryptor::Encryptor()
17     : key_(NULL),
18       mode_(CBC) {
19   EnsureNSSInit();
20 }
21 
~Encryptor()22 Encryptor::~Encryptor() {
23 }
24 
Init(SymmetricKey * key,Mode mode,const std::string & iv)25 bool Encryptor::Init(SymmetricKey* key, Mode mode, const std::string& iv) {
26   DCHECK(key);
27   DCHECK_EQ(CBC, mode);
28 
29   key_ = key;
30   mode_ = mode;
31 
32   if (iv.size() != AES_BLOCK_SIZE)
33     return false;
34 
35   slot_.reset(PK11_GetBestSlot(CKM_AES_CBC_PAD, NULL));
36   if (!slot_.get())
37     return false;
38 
39   SECItem iv_item;
40   iv_item.type = siBuffer;
41   iv_item.data = reinterpret_cast<unsigned char*>(
42       const_cast<char *>(iv.data()));
43   iv_item.len = iv.size();
44 
45   param_.reset(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item));
46   if (!param_.get())
47     return false;
48 
49   return true;
50 }
51 
Encrypt(const std::string & plaintext,std::string * ciphertext)52 bool Encryptor::Encrypt(const std::string& plaintext, std::string* ciphertext) {
53   ScopedPK11Context context(PK11_CreateContextBySymKey(CKM_AES_CBC_PAD,
54                                                        CKA_ENCRYPT,
55                                                        key_->key(),
56                                                        param_.get()));
57   if (!context.get())
58     return false;
59 
60   size_t ciphertext_len = plaintext.size() + AES_BLOCK_SIZE;
61   std::vector<unsigned char> buffer(ciphertext_len);
62 
63   int op_len;
64   SECStatus rv = PK11_CipherOp(context.get(),
65                                &buffer[0],
66                                &op_len,
67                                ciphertext_len,
68                                reinterpret_cast<unsigned char*>(
69                                    const_cast<char*>(plaintext.data())),
70                                plaintext.size());
71   if (SECSuccess != rv)
72     return false;
73 
74   unsigned int digest_len;
75   rv = PK11_DigestFinal(context.get(),
76                         &buffer[op_len],
77                         &digest_len,
78                         ciphertext_len - op_len);
79   if (SECSuccess != rv)
80     return false;
81 
82   ciphertext->assign(reinterpret_cast<char *>(&buffer[0]),
83                      op_len + digest_len);
84   return true;
85 }
86 
Decrypt(const std::string & ciphertext,std::string * plaintext)87 bool Encryptor::Decrypt(const std::string& ciphertext, std::string* plaintext) {
88   if (ciphertext.empty())
89     return false;
90 
91   ScopedPK11Context context(PK11_CreateContextBySymKey(CKM_AES_CBC_PAD,
92                                                        CKA_DECRYPT,
93                                                        key_->key(),
94                                                        param_.get()));
95   if (!context.get())
96     return false;
97 
98   size_t plaintext_len = ciphertext.size();
99   std::vector<unsigned char> buffer(plaintext_len);
100 
101   int op_len;
102   SECStatus rv = PK11_CipherOp(context.get(),
103                                &buffer[0],
104                                &op_len,
105                                plaintext_len,
106                                reinterpret_cast<unsigned char*>(
107                                    const_cast<char*>(ciphertext.data())),
108                                ciphertext.size());
109   if (SECSuccess != rv)
110     return false;
111 
112   unsigned int digest_len;
113   rv = PK11_DigestFinal(context.get(),
114                         &buffer[op_len],
115                         &digest_len,
116                         plaintext_len - op_len);
117   if (SECSuccess != rv)
118     return false;
119 
120   plaintext->assign(reinterpret_cast<char *>(&buffer[0]),
121                     op_len + digest_len);
122   return true;
123 }
124 
125 }  // namespace crypto
126