1 // Copyright 2013 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.
5 #include "components/autofill/content/browser/wallet/full_wallet.h"
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "components/autofill/core/browser/autofill_type.h"
12 #include "components/autofill/core/browser/credit_card.h"
16 const size_t kPanSize
= 16;
17 const size_t kBinSize
= 6;
18 const size_t kCvnSize
= 3;
19 const size_t kEncryptedRestSize
= 12;
21 } // anonymous namespace
26 FullWallet::FullWallet(int expiration_month
,
28 const std::string
& iin
,
29 const std::string
& encrypted_rest
,
30 scoped_ptr
<Address
> billing_address
,
31 scoped_ptr
<Address
> shipping_address
,
32 const std::vector
<RequiredAction
>& required_actions
)
33 : expiration_month_(expiration_month
),
34 expiration_year_(expiration_year
),
36 encrypted_rest_(encrypted_rest
),
37 billing_address_(billing_address
.Pass()),
38 shipping_address_(shipping_address
.Pass()),
39 required_actions_(required_actions
) {
40 DCHECK(required_actions_
.size() > 0 || billing_address_
.get());
43 FullWallet::~FullWallet() {}
46 scoped_ptr
<FullWallet
>
47 FullWallet::CreateFullWallet(const base::DictionaryValue
& dictionary
) {
48 const base::ListValue
* required_actions_list
;
49 std::vector
<RequiredAction
> required_actions
;
50 if (dictionary
.GetList("required_action", &required_actions_list
)) {
51 for (size_t i
= 0; i
< required_actions_list
->GetSize(); ++i
) {
52 std::string action_string
;
53 if (required_actions_list
->GetString(i
, &action_string
)) {
54 RequiredAction action
= ParseRequiredActionFromString(action_string
);
55 if (!ActionAppliesToFullWallet(action
)) {
56 DLOG(ERROR
) << "Response from Google wallet with bad required action:"
57 " \"" << action_string
<< "\"";
58 return scoped_ptr
<FullWallet
>();
60 required_actions
.push_back(action
);
63 if (required_actions
.size() > 0) {
64 return scoped_ptr
<FullWallet
>(new FullWallet(-1,
68 scoped_ptr
<Address
>(),
69 scoped_ptr
<Address
>(),
73 DVLOG(1) << "Response from Google wallet missing required actions";
77 if (!dictionary
.GetInteger("expiration_month", &expiration_month
)) {
78 DLOG(ERROR
) << "Response from Google wallet missing expiration month";
79 return scoped_ptr
<FullWallet
>();
83 if (!dictionary
.GetInteger("expiration_year", &expiration_year
)) {
84 DLOG(ERROR
) << "Response from Google wallet missing expiration year";
85 return scoped_ptr
<FullWallet
>();
89 if (!dictionary
.GetString("iin", &iin
)) {
90 DLOG(ERROR
) << "Response from Google wallet missing iin";
91 return scoped_ptr
<FullWallet
>();
94 std::string encrypted_rest
;
95 if (!dictionary
.GetString("rest", &encrypted_rest
)) {
96 DLOG(ERROR
) << "Response from Google wallet missing rest";
97 return scoped_ptr
<FullWallet
>();
100 const base::DictionaryValue
* billing_address_dict
;
101 if (!dictionary
.GetDictionary("billing_address", &billing_address_dict
)) {
102 DLOG(ERROR
) << "Response from Google wallet missing billing address";
103 return scoped_ptr
<FullWallet
>();
106 scoped_ptr
<Address
> billing_address
=
107 Address::CreateAddress(*billing_address_dict
);
108 if (!billing_address
.get()) {
109 DLOG(ERROR
) << "Response from Google wallet has malformed billing address";
110 return scoped_ptr
<FullWallet
>();
113 const base::DictionaryValue
* shipping_address_dict
;
114 scoped_ptr
<Address
> shipping_address
;
115 if (dictionary
.GetDictionary("shipping_address", &shipping_address_dict
)) {
117 Address::CreateAddressWithID(*shipping_address_dict
);
119 DVLOG(1) << "Response from Google wallet missing shipping address";
122 return scoped_ptr
<FullWallet
>(new FullWallet(expiration_month
,
126 billing_address
.Pass(),
127 shipping_address
.Pass(),
132 scoped_ptr
<FullWallet
>
133 FullWallet::CreateFullWalletFromClearText(
134 int expiration_month
,
136 const std::string
& pan
,
137 const std::string
& cvn
,
138 scoped_ptr
<Address
> billing_address
,
139 scoped_ptr
<Address
> shipping_address
) {
140 DCHECK(billing_address
);
141 DCHECK(!pan
.empty());
142 DCHECK(!cvn
.empty());
144 scoped_ptr
<FullWallet
> wallet(new FullWallet(
147 std::string(), // no iin -- clear text pan/cvn are set below.
148 std::string(), // no encrypted_rest -- clear text pan/cvn are set below.
149 billing_address
.Pass(),
150 shipping_address
.Pass(),
151 std::vector
<RequiredAction
>())); // no required actions in clear text.
154 return wallet
.Pass();
157 base::string16
FullWallet::GetInfo(const std::string
& app_locale
,
158 const AutofillType
& type
) {
159 switch (type
.GetStorableType()) {
160 case CREDIT_CARD_NUMBER
:
161 return base::ASCIIToUTF16(GetPan());
163 case CREDIT_CARD_NAME
:
164 return billing_address()->recipient_name();
166 case CREDIT_CARD_VERIFICATION_CODE
:
167 return base::ASCIIToUTF16(GetCvn());
169 case CREDIT_CARD_EXP_MONTH
:
170 if (expiration_month() == 0)
171 return base::string16();
172 return base::IntToString16(expiration_month());
174 case CREDIT_CARD_EXP_4_DIGIT_YEAR
:
175 if (expiration_year() == 0)
176 return base::string16();
177 return base::IntToString16(expiration_year());
179 case CREDIT_CARD_EXP_2_DIGIT_YEAR
:
180 if (expiration_year() == 0)
181 return base::string16();
182 return base::IntToString16(expiration_year() % 100);
184 case CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR
:
185 if (expiration_month() == 0 || expiration_year() == 0)
186 return base::string16();
187 return base::IntToString16(expiration_month()) + base::ASCIIToUTF16("/") +
188 base::IntToString16(expiration_year() % 100);
190 case CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR
:
191 if (expiration_month() == 0 || expiration_year() == 0)
192 return base::string16();
193 return base::IntToString16(expiration_month()) + base::ASCIIToUTF16("/") +
194 base::IntToString16(expiration_year());
196 case CREDIT_CARD_TYPE
: {
197 const char* const internal_type
=
198 CreditCard::GetCreditCardType(base::ASCIIToUTF16(GetPan()));
199 if (internal_type
== kGenericCard
)
200 return base::string16();
201 return CreditCard::TypeForDisplay(internal_type
);
205 switch (type
.group()) {
208 case ADDRESS_BILLING
:
209 return billing_address_
->GetInfo(type
, app_locale
);
215 return shipping_address_
->GetInfo(type
, app_locale
);
221 bool FullWallet::HasRequiredAction(RequiredAction action
) const {
222 DCHECK(ActionAppliesToFullWallet(action
));
223 return std::find(required_actions_
.begin(),
224 required_actions_
.end(),
225 action
) != required_actions_
.end();
228 base::string16
FullWallet::TypeAndLastFourDigits() {
230 card
.SetRawInfo(CREDIT_CARD_NUMBER
, base::ASCIIToUTF16(GetPan()));
231 return card
.TypeAndLastFourDigits();
234 const std::string
& FullWallet::GetPan() {
240 bool FullWallet::operator==(const FullWallet
& other
) const {
241 if (expiration_month_
!= other
.expiration_month_
)
244 if (expiration_year_
!= other
.expiration_year_
)
247 if (iin_
!= other
.iin_
)
250 if (encrypted_rest_
!= other
.encrypted_rest_
)
253 if (billing_address_
.get() && other
.billing_address_
.get()) {
254 if (*billing_address_
.get() != *other
.billing_address_
.get())
256 } else if (billing_address_
.get() || other
.billing_address_
.get()) {
260 if (shipping_address_
.get() && other
.shipping_address_
.get()) {
261 if (*shipping_address_
.get() != *other
.shipping_address_
.get())
263 } else if (shipping_address_
.get() || other
.shipping_address_
.get()) {
267 if (required_actions_
!= other
.required_actions_
)
273 bool FullWallet::operator!=(const FullWallet
& other
) const {
274 return !(*this == other
);
277 void FullWallet::DecryptCardInfo() {
278 // |encrypted_rest_| must be of length |kEncryptedRestSize| in order for
279 // decryption to succeed and the server will not pad it with zeros.
280 while (encrypted_rest_
.size() < kEncryptedRestSize
) {
281 encrypted_rest_
= '0' + encrypted_rest_
;
284 DCHECK_EQ(kEncryptedRestSize
, encrypted_rest_
.size());
286 std::vector
<uint8
> operating_data
;
287 // Convert |encrypted_rest_| to bytes so we can decrypt it with |otp|.
288 if (!base::HexStringToBytes(encrypted_rest_
, &operating_data
)) {
289 DLOG(ERROR
) << "Failed to parse encrypted rest";
293 // Ensure |one_time_pad_| and |encrypted_rest_| are of the same length
294 // otherwise something has gone wrong and we can't decrypt the data.
295 DCHECK_EQ(one_time_pad_
.size(), operating_data
.size());
297 std::vector
<uint8
> results
;
298 // XOR |otp| with the encrypted data to decrypt.
299 for (size_t i
= 0; i
< one_time_pad_
.size(); ++i
)
300 results
.push_back(one_time_pad_
[i
] ^ operating_data
[i
]);
302 // There is no uint8* to int64 so convert the decrypted data to hex and then
303 // parse the hex to an int64 before getting the int64 as a string.
304 std::string hex_decrypted
= base::HexEncode(&(results
[0]), results
.size());
307 if (!base::HexStringToInt64(hex_decrypted
, &decrypted
)) {
308 DLOG(ERROR
) << "Failed to parse decrypted data in hex to int64";
311 std::string card_info
= base::Int64ToString(decrypted
);
313 size_t padded_length
= kPanSize
- kBinSize
+ kCvnSize
;
314 // |card_info| is PAN without the IIN concatenated with the CVN, i.e.
315 // PANPANPANPCVN. If what was decrypted is not of that size the front needs
316 // to be padded with 0's until it is.
317 if (card_info
.size() != padded_length
)
318 card_info
.insert(card_info
.begin(), padded_length
- card_info
.size(), '0');
320 // Separate out the PAN from the CVN.
321 size_t split
= kPanSize
- kBinSize
;
322 cvn_
= card_info
.substr(split
);
323 pan_
= iin_
+ card_info
.substr(0, split
);
326 const std::string
& FullWallet::GetCvn() {
332 } // namespace wallet
333 } // namespace autofill