blob: 1ae8dab4281f57b62b898e2e2fefa538997335cb [file] [log] [blame]
Chung-yih Wangeec11822009-07-02 00:22:04 +08001/*
2**
3** Copyright 2009, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17#define LOG_TAG "CertTool"
18
19#include <string.h>
20#include <jni.h>
21#include <cutils/log.h>
Chung-yih Wangc9c119e2009-07-16 19:54:33 +080022#include <openssl/pkcs12.h>
Chung-yih Wangeec11822009-07-02 00:22:04 +080023#include <openssl/x509v3.h>
24
25#include "cert.h"
26
Chung-yih Wangc9c119e2009-07-16 19:54:33 +080027typedef int PKCS12_KEYSTORE_FUNC(PKCS12_KEYSTORE *store, char *buf, int size);
28
Chung-yih Wangeec11822009-07-02 00:22:04 +080029jstring
30android_security_CertTool_generateCertificateRequest(JNIEnv* env,
31 jobject thiz,
32 jint bits,
33 jstring subject)
34
35{
36 char csr[REPLY_MAX];
37 if (gen_csr(bits, subject, csr) == 0) {
38 return (*env)->NewStringUTF(env, csr);
39 }
40 return NULL;
41}
42
43jboolean
44android_security_CertTool_isPkcs12Keystore(JNIEnv* env,
45 jobject thiz,
46 jbyteArray data)
47{
Chung-yih Wangeec11822009-07-02 00:22:04 +080048 int len = (*env)->GetArrayLength(env, data);
49
Chung-yih Wangc9c119e2009-07-16 19:54:33 +080050 if (len > 0) {
51 PKCS12 *handle = NULL;
52 char buf[len];
53
54 (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf);
55 return (jboolean)is_pkcs12(buf, len);
56 } else {
57 return 0;
58 }
59}
60
61jint
62android_security_CertTool_getPkcs12Handle(JNIEnv* env,
63 jobject thiz,
64 jbyteArray data,
65 jstring jPassword)
66{
67 jboolean bIsCopy;
68 int len = (*env)->GetArrayLength(env, data);
69 const char* passwd = (*env)->GetStringUTFChars(env, jPassword , &bIsCopy);
70
71 if (len > 0) {
72 PKCS12_KEYSTORE *handle = NULL;
73 char buf[len];
74
75 (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf);
76 handle = get_pkcs12_keystore_handle(buf, len, passwd);
77 (*env)->ReleaseStringUTFChars(env, jPassword, passwd);
78 return (jint)handle;
79 } else {
80 return 0;
81 }
82}
83
84jstring call_pkcs12_ks_func(PKCS12_KEYSTORE_FUNC *func,
85 JNIEnv* env,
86 jobject thiz,
87 jint phandle)
88{
89 char buf[REPLY_MAX];
90
91 if (phandle == 0) return NULL;
92 if (func((PKCS12_KEYSTORE*)phandle, buf, sizeof(buf)) == 0) {
93 return (*env)->NewStringUTF(env, buf);
94 }
95 return NULL;
96}
97
98jstring
99android_security_CertTool_getPkcs12Certificate(JNIEnv* env,
100 jobject thiz,
101 jint phandle)
102{
103 return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)get_pkcs12_certificate,
104 env, thiz, phandle);
105}
106
107jstring
108android_security_CertTool_getPkcs12PrivateKey(JNIEnv* env,
109 jobject thiz,
110 jint phandle)
111{
112 return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)get_pkcs12_private_key,
113 env, thiz, phandle);
114}
115
116jstring
117android_security_CertTool_popPkcs12CertificateStack(JNIEnv* env,
118 jobject thiz,
119 jint phandle)
120{
121 return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)pop_pkcs12_certs_stack,
122 env, thiz, phandle);
123}
124
125void android_security_CertTool_freePkcs12Handle(JNIEnv* env,
126 jobject thiz,
127 jint handle)
128{
129 if (handle != 0) free_pkcs12_keystore((PKCS12_KEYSTORE*)handle);
Chung-yih Wangeec11822009-07-02 00:22:04 +0800130}
131
132jint
133android_security_CertTool_generateX509Certificate(JNIEnv* env,
134 jobject thiz,
135 jbyteArray data)
136{
137 char buf[REPLY_MAX];
138 int len = (*env)->GetArrayLength(env, data);
139
140 if (len > REPLY_MAX) return 0;
141 (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf);
142 return (jint) parse_cert(buf, len);
143}
144
145jboolean android_security_CertTool_isCaCertificate(JNIEnv* env,
146 jobject thiz,
147 jint handle)
148{
149 return (handle == 0) ? (jboolean)0 : (jboolean) is_ca_cert((X509*)handle);
150}
151
152jstring android_security_CertTool_getIssuerDN(JNIEnv* env,
153 jobject thiz,
154 jint handle)
155{
156 char issuer[MAX_CERT_NAME_LEN];
157
158 if (handle == 0) return NULL;
159 if (get_issuer_name((X509*)handle, issuer, MAX_CERT_NAME_LEN)) return NULL;
160 return (*env)->NewStringUTF(env, issuer);
161}
162
163jstring android_security_CertTool_getCertificateDN(JNIEnv* env,
164 jobject thiz,
165 jint handle)
166{
167 char name[MAX_CERT_NAME_LEN];
168 if (handle == 0) return NULL;
169 if (get_cert_name((X509*)handle, name, MAX_CERT_NAME_LEN)) return NULL;
170 return (*env)->NewStringUTF(env, name);
171}
172
173jstring android_security_CertTool_getPrivateKeyPEM(JNIEnv* env,
174 jobject thiz,
175 jint handle)
176{
177 char pem[MAX_PEM_LENGTH];
178 if (handle == 0) return NULL;
179 if (get_private_key_pem((X509*)handle, pem, MAX_PEM_LENGTH)) return NULL;
180 return (*env)->NewStringUTF(env, pem);
181}
182
183void android_security_CertTool_freeX509Certificate(JNIEnv* env,
184 jobject thiz,
185 jint handle)
186{
187 if (handle != 0) X509_free((X509*)handle);
188}
189
190/*
191 * Table of methods associated with the CertTool class.
192 */
193static JNINativeMethod gCertToolMethods[] = {
194 /* name, signature, funcPtr */
195 {"generateCertificateRequest", "(ILjava/lang/String;)Ljava/lang/String;",
196 (void*)android_security_CertTool_generateCertificateRequest},
Chung-yih Wang699ca3f2009-07-04 22:19:51 +0800197 {"isPkcs12Keystore", "([B)Z",
Chung-yih Wangeec11822009-07-02 00:22:04 +0800198 (void*)android_security_CertTool_isPkcs12Keystore},
Chung-yih Wangc9c119e2009-07-16 19:54:33 +0800199 {"getPkcs12Handle", "([BLjava/lang/String;)I",
200 (void*)android_security_CertTool_getPkcs12Handle},
201 {"getPkcs12Certificate", "(I)Ljava/lang/String;",
202 (void*)android_security_CertTool_getPkcs12Certificate},
203 {"getPkcs12PrivateKey", "(I)Ljava/lang/String;",
204 (void*)android_security_CertTool_getPkcs12PrivateKey},
205 {"popPkcs12CertificateStack", "(I)Ljava/lang/String;",
206 (void*)android_security_CertTool_popPkcs12CertificateStack},
207 {"freePkcs12Handle", "(I)V",
208 (void*)android_security_CertTool_freePkcs12Handle},
Chung-yih Wang699ca3f2009-07-04 22:19:51 +0800209 {"generateX509Certificate", "([B)I",
Chung-yih Wangeec11822009-07-02 00:22:04 +0800210 (void*)android_security_CertTool_generateX509Certificate},
211 {"isCaCertificate", "(I)Z",
212 (void*)android_security_CertTool_isCaCertificate},
213 {"getIssuerDN", "(I)Ljava/lang/String;",
214 (void*)android_security_CertTool_getIssuerDN},
215 {"getCertificateDN", "(I)Ljava/lang/String;",
216 (void*)android_security_CertTool_getCertificateDN},
217 {"getPrivateKeyPEM", "(I)Ljava/lang/String;",
218 (void*)android_security_CertTool_getPrivateKeyPEM},
219 {"freeX509Certificate", "(I)V",
220 (void*)android_security_CertTool_freeX509Certificate},
221};
222
223/*
224 * Register several native methods for one class.
225 */
226static int registerNatives(JNIEnv* env, const char* className,
227 JNINativeMethod* gMethods, int numMethods)
228{
229 jclass clazz;
230
231 clazz = (*env)->FindClass(env, className);
232 if (clazz == NULL) {
233 LOGE("Can not find class %s\n", className);
234 return JNI_FALSE;
235 }
236
237 if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
238 LOGE("Can not RegisterNatives\n");
239 return JNI_FALSE;
240 }
241
242 return JNI_TRUE;
243}
244
245jint JNI_OnLoad(JavaVM* vm, void* reserved)
246{
247 JNIEnv* env = NULL;
248 jint result = -1;
249
250
251 if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
252 goto bail;
253 }
254
255 if (!registerNatives(env, "android/security/CertTool",
256 gCertToolMethods, nelem(gCertToolMethods))) {
257 goto bail;
258 }
259
260 /* success -- return valid version number */
261 result = JNI_VERSION_1_4;
262
263bail:
264 return result;
265}