1// Copyright (c) 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.
4
5#include "net/android/keystore.h"
6
7#include <vector>
8
9#include "base/android/jni_android.h"
10#include "base/android/jni_array.h"
11#include "base/logging.h"
12#include "jni/AndroidKeyStore_jni.h"
13#include "net/android/android_private_key.h"
14
15using base::android::AttachCurrentThread;
16using base::android::HasException;
17using base::android::JavaByteArrayToByteVector;
18using base::android::ScopedJavaLocalRef;
19using base::android::ToJavaByteArray;
20using base::android::JavaArrayOfByteArrayToStringVector;
21
22namespace net {
23namespace android {
24
25bool GetRSAKeyModulus(
26    jobject private_key_ref,
27    std::vector<uint8>* result) {
28  JNIEnv* env = AttachCurrentThread();
29
30  ScopedJavaLocalRef<jbyteArray> modulus_ref =
31      Java_AndroidKeyStore_getRSAKeyModulus(env,
32                                            GetKeyStore(private_key_ref).obj(),
33                                            private_key_ref);
34  if (modulus_ref.is_null())
35    return false;
36
37  JavaByteArrayToByteVector(env, modulus_ref.obj(), result);
38  return true;
39}
40
41bool GetDSAKeyParamQ(jobject private_key_ref,
42                     std::vector<uint8>* result) {
43  JNIEnv* env = AttachCurrentThread();
44
45  ScopedJavaLocalRef<jbyteArray> q_ref =
46      Java_AndroidKeyStore_getDSAKeyParamQ(
47          env,
48          GetKeyStore(private_key_ref).obj(),
49          private_key_ref);
50  if (q_ref.is_null())
51    return false;
52
53  JavaByteArrayToByteVector(env, q_ref.obj(), result);
54  return true;
55}
56
57bool GetECKeyOrder(jobject private_key_ref,
58                   std::vector<uint8>* result) {
59  JNIEnv* env = AttachCurrentThread();
60
61  ScopedJavaLocalRef<jbyteArray> order_ref =
62      Java_AndroidKeyStore_getECKeyOrder(
63          env,
64          GetKeyStore(private_key_ref).obj(),
65          private_key_ref);
66
67  if (order_ref.is_null())
68    return false;
69
70  JavaByteArrayToByteVector(env, order_ref.obj(), result);
71  return true;
72}
73
74bool GetPrivateKeyEncodedBytes(jobject private_key_ref,
75                               std::vector<uint8>* result) {
76  JNIEnv* env = AttachCurrentThread();
77
78  ScopedJavaLocalRef<jbyteArray> encoded_ref =
79      Java_AndroidKeyStore_getPrivateKeyEncodedBytes(
80          env,
81          GetKeyStore(private_key_ref).obj(),
82          private_key_ref);
83  if (encoded_ref.is_null())
84    return false;
85
86  JavaByteArrayToByteVector(env, encoded_ref.obj(), result);
87  return true;
88}
89
90bool RawSignDigestWithPrivateKey(
91    jobject private_key_ref,
92    const base::StringPiece& digest,
93    std::vector<uint8>* signature) {
94  JNIEnv* env = AttachCurrentThread();
95
96  // Convert message to byte[] array.
97  ScopedJavaLocalRef<jbyteArray> digest_ref =
98      ToJavaByteArray(env,
99                      reinterpret_cast<const uint8*>(digest.data()),
100                      digest.length());
101  DCHECK(!digest_ref.is_null());
102
103  // Invoke platform API
104  ScopedJavaLocalRef<jbyteArray> signature_ref =
105      Java_AndroidKeyStore_rawSignDigestWithPrivateKey(
106          env,
107          GetKeyStore(private_key_ref).obj(),
108          private_key_ref,
109          digest_ref.obj());
110  if (HasException(env) || signature_ref.is_null())
111    return false;
112
113  // Write signature to string.
114  JavaByteArrayToByteVector(env, signature_ref.obj(), signature);
115  return true;
116}
117
118PrivateKeyType GetPrivateKeyType(jobject private_key_ref) {
119  JNIEnv* env = AttachCurrentThread();
120  int type = Java_AndroidKeyStore_getPrivateKeyType(
121      env,
122      GetKeyStore(private_key_ref).obj(),
123      private_key_ref);
124  return static_cast<PrivateKeyType>(type);
125}
126
127AndroidEVP_PKEY* GetOpenSSLSystemHandleForPrivateKey(jobject private_key_ref) {
128  JNIEnv* env = AttachCurrentThread();
129  // Note: the pointer is passed as a jint here because that's how it
130  // is stored in the Java object. Java doesn't have a primitive type
131  // like intptr_t that matches the size of pointers on the host
132  // machine, and Android only runs on 32-bit CPUs.
133  //
134  // Given that this routine shall only be called on Android < 4.2,
135  // this won't be a problem in the far future (e.g. when Android gets
136  // ported to 64-bit environments, if ever).
137  long pkey = Java_AndroidKeyStore_getOpenSSLHandleForPrivateKey(
138      env,
139      GetKeyStore(private_key_ref).obj(),
140      private_key_ref);
141  return reinterpret_cast<AndroidEVP_PKEY*>(pkey);
142}
143
144ScopedJavaLocalRef<jobject> GetOpenSSLEngineForPrivateKey(
145    jobject private_key_ref) {
146  JNIEnv* env = AttachCurrentThread();
147  ScopedJavaLocalRef<jobject> engine =
148      Java_AndroidKeyStore_getOpenSSLEngineForPrivateKey(
149          env,
150          GetKeyStore(private_key_ref).obj(),
151          private_key_ref);
152  return engine;
153}
154
155void ReleaseKey(jobject private_key_ref) {
156  JNIEnv* env = AttachCurrentThread();
157  Java_AndroidKeyStore_releaseKey(env,
158                                  GetKeyStore(private_key_ref).obj(),
159                                  private_key_ref);
160  env->DeleteGlobalRef(private_key_ref);
161}
162
163bool RegisterKeyStore(JNIEnv* env) {
164  return RegisterNativesImpl(env);
165}
166
167}  // namespace android
168}  // namespace net
169