1// Copyright 2014 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 "chrome/renderer/extensions/enterprise_platform_keys_natives.h"
6
7#include <string>
8
9#include "base/values.h"
10#include "chrome/renderer/extensions/chrome_v8_context.h"
11#include "content/public/renderer/v8_value_converter.h"
12#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
13#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
14#include "third_party/WebKit/public/platform/WebString.h"
15#include "third_party/WebKit/public/platform/WebVector.h"
16#include "third_party/WebKit/public/web/WebCryptoNormalize.h"
17
18namespace extensions {
19
20namespace {
21
22bool StringToWebCryptoOperation(const std::string& str,
23                                blink::WebCryptoOperation* op) {
24  if (str == "GenerateKey") {
25    *op = blink::WebCryptoOperationGenerateKey;
26    return true;
27  }
28  if (str == "Sign") {
29    *op = blink::WebCryptoOperationSign;
30    return true;
31  }
32  if (str == "Verify") {
33    *op = blink::WebCryptoOperationVerify;
34    return true;
35  }
36  return false;
37}
38
39scoped_ptr<base::DictionaryValue> WebCryptoAlgorithmToBaseValue(
40    const blink::WebCryptoAlgorithm& algorithm) {
41  DCHECK(!algorithm.isNull());
42
43  scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
44  const blink::WebCryptoAlgorithmInfo* info =
45      blink::WebCryptoAlgorithm::lookupAlgorithmInfo(algorithm.id());
46  dict->SetStringWithoutPathExpansion("name", info->name);
47  const blink::WebCryptoRsaHashedKeyGenParams* rsaHashedKeyGen =
48      algorithm.rsaHashedKeyGenParams();
49  if (rsaHashedKeyGen) {
50    dict->SetIntegerWithoutPathExpansion("modulusLength",
51                                         rsaHashedKeyGen->modulusLengthBits());
52    const blink::WebVector<unsigned char>& public_exponent =
53        rsaHashedKeyGen->publicExponent();
54    dict->SetWithoutPathExpansion(
55        "publicExponent",
56        base::BinaryValue::CreateWithCopiedBuffer(
57            reinterpret_cast<const char*>(public_exponent.data()),
58            public_exponent.size()));
59
60    const blink::WebCryptoAlgorithm& hash = rsaHashedKeyGen->hash();
61    DCHECK(!hash.isNull());
62    const blink::WebCryptoAlgorithmInfo* hash_info =
63        blink::WebCryptoAlgorithm::lookupAlgorithmInfo(hash.id());
64
65    scoped_ptr<base::DictionaryValue> hash_dict(new base::DictionaryValue);
66    hash_dict->SetStringWithoutPathExpansion("name", hash_info->name);
67    dict->SetWithoutPathExpansion("hash", hash_dict.release());
68  }
69  // Otherwise, |algorithm| is missing support here or no parameters were
70  // required.
71  return dict.Pass();
72}
73
74}  // namespace
75
76EnterprisePlatformKeysNatives::EnterprisePlatformKeysNatives(
77    ScriptContext* context)
78    : ObjectBackedNativeHandler(context) {
79  RouteFunction("NormalizeAlgorithm",
80                base::Bind(&EnterprisePlatformKeysNatives::NormalizeAlgorithm,
81                           base::Unretained(this)));
82}
83
84void EnterprisePlatformKeysNatives::NormalizeAlgorithm(
85    const v8::FunctionCallbackInfo<v8::Value>& call_info) {
86  DCHECK_EQ(call_info.Length(), 2);
87  DCHECK(call_info[0]->IsObject());
88  DCHECK(call_info[1]->IsString());
89
90  blink::WebCryptoOperation operation;
91  if (!StringToWebCryptoOperation(*v8::String::Utf8Value(call_info[1]),
92                                  &operation)) {
93    return;
94  }
95
96  blink::WebString error_details;
97  int exception_code = 0;
98
99  blink::WebCryptoAlgorithm algorithm =
100      blink::normalizeCryptoAlgorithm(call_info[0]->ToObject(),
101                                      operation,
102                                      &exception_code,
103                                      &error_details,
104                                      call_info.GetIsolate());
105
106  scoped_ptr<base::DictionaryValue> algorithm_dict;
107  if (!algorithm.isNull())
108    algorithm_dict = WebCryptoAlgorithmToBaseValue(algorithm);
109
110  if (!algorithm_dict)
111    return;
112
113  scoped_ptr<content::V8ValueConverter> converter(
114      content::V8ValueConverter::create());
115  call_info.GetReturnValue().Set(
116      converter->ToV8Value(algorithm_dict.get(), context()->v8_context()));
117}
118
119}  // namespace extensions
120