blob: b36b34a2c55175d6764d6bd9ec607ba97557a6eb [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,
Chung-yih Wang19145232009-07-28 15:15:51 +080033 jstring jChallenge)
Chung-yih Wangeec11822009-07-02 00:22:04 +080034
35{
Chung-yih Wang19145232009-07-28 15:15:51 +080036 int ret = -1;
37 jboolean bIsCopy;
Chung-yih Wangeec11822009-07-02 00:22:04 +080038 char csr[REPLY_MAX];
Chung-yih Wang19145232009-07-28 15:15:51 +080039 const char* challenge = (*env)->GetStringUTFChars(env, jChallenge, &bIsCopy);
40
41 ret = gen_csr(bits, challenge , csr);
42 (*env)->ReleaseStringUTFChars(env, jChallenge, challenge);
43 if (ret == 0) return (*env)->NewStringUTF(env, csr);
Chung-yih Wangeec11822009-07-02 00:22:04 +080044 return NULL;
45}
46
47jboolean
48android_security_CertTool_isPkcs12Keystore(JNIEnv* env,
49 jobject thiz,
50 jbyteArray data)
51{
Chung-yih Wangeec11822009-07-02 00:22:04 +080052 int len = (*env)->GetArrayLength(env, data);
53
Chung-yih Wangc9c119e2009-07-16 19:54:33 +080054 if (len > 0) {
55 PKCS12 *handle = NULL;
56 char buf[len];
57
58 (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf);
59 return (jboolean)is_pkcs12(buf, len);
60 } else {
61 return 0;
62 }
63}
64
65jint
66android_security_CertTool_getPkcs12Handle(JNIEnv* env,
67 jobject thiz,
68 jbyteArray data,
69 jstring jPassword)
70{
71 jboolean bIsCopy;
72 int len = (*env)->GetArrayLength(env, data);
73 const char* passwd = (*env)->GetStringUTFChars(env, jPassword , &bIsCopy);
74
75 if (len > 0) {
76 PKCS12_KEYSTORE *handle = NULL;
77 char buf[len];
78
79 (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf);
80 handle = get_pkcs12_keystore_handle(buf, len, passwd);
81 (*env)->ReleaseStringUTFChars(env, jPassword, passwd);
82 return (jint)handle;
83 } else {
84 return 0;
85 }
86}
87
88jstring call_pkcs12_ks_func(PKCS12_KEYSTORE_FUNC *func,
89 JNIEnv* env,
90 jobject thiz,
91 jint phandle)
92{
93 char buf[REPLY_MAX];
94
95 if (phandle == 0) return NULL;
96 if (func((PKCS12_KEYSTORE*)phandle, buf, sizeof(buf)) == 0) {
97 return (*env)->NewStringUTF(env, buf);
98 }
99 return NULL;
100}
101
102jstring
103android_security_CertTool_getPkcs12Certificate(JNIEnv* env,
104 jobject thiz,
105 jint phandle)
106{
107 return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)get_pkcs12_certificate,
108 env, thiz, phandle);
109}
110
111jstring
112android_security_CertTool_getPkcs12PrivateKey(JNIEnv* env,
113 jobject thiz,
114 jint phandle)
115{
116 return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)get_pkcs12_private_key,
117 env, thiz, phandle);
118}
119
120jstring
121android_security_CertTool_popPkcs12CertificateStack(JNIEnv* env,
122 jobject thiz,
123 jint phandle)
124{
125 return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)pop_pkcs12_certs_stack,
126 env, thiz, phandle);
127}
128
129void android_security_CertTool_freePkcs12Handle(JNIEnv* env,
130 jobject thiz,
131 jint handle)
132{
133 if (handle != 0) free_pkcs12_keystore((PKCS12_KEYSTORE*)handle);
Chung-yih Wangeec11822009-07-02 00:22:04 +0800134}
135
136jint
137android_security_CertTool_generateX509Certificate(JNIEnv* env,
138 jobject thiz,
139 jbyteArray data)
140{
141 char buf[REPLY_MAX];
142 int len = (*env)->GetArrayLength(env, data);
143
144 if (len > REPLY_MAX) return 0;
145 (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf);
146 return (jint) parse_cert(buf, len);
147}
148
149jboolean android_security_CertTool_isCaCertificate(JNIEnv* env,
150 jobject thiz,
151 jint handle)
152{
153 return (handle == 0) ? (jboolean)0 : (jboolean) is_ca_cert((X509*)handle);
154}
155
156jstring android_security_CertTool_getIssuerDN(JNIEnv* env,
157 jobject thiz,
158 jint handle)
159{
160 char issuer[MAX_CERT_NAME_LEN];
161
162 if (handle == 0) return NULL;
163 if (get_issuer_name((X509*)handle, issuer, MAX_CERT_NAME_LEN)) return NULL;
164 return (*env)->NewStringUTF(env, issuer);
165}
166
167jstring android_security_CertTool_getCertificateDN(JNIEnv* env,
168 jobject thiz,
169 jint handle)
170{
171 char name[MAX_CERT_NAME_LEN];
172 if (handle == 0) return NULL;
173 if (get_cert_name((X509*)handle, name, MAX_CERT_NAME_LEN)) return NULL;
174 return (*env)->NewStringUTF(env, name);
175}
176
177jstring android_security_CertTool_getPrivateKeyPEM(JNIEnv* env,
178 jobject thiz,
179 jint handle)
180{
181 char pem[MAX_PEM_LENGTH];
182 if (handle == 0) return NULL;
183 if (get_private_key_pem((X509*)handle, pem, MAX_PEM_LENGTH)) return NULL;
184 return (*env)->NewStringUTF(env, pem);
185}
186
187void android_security_CertTool_freeX509Certificate(JNIEnv* env,
188 jobject thiz,
189 jint handle)
190{
191 if (handle != 0) X509_free((X509*)handle);
192}
193
194/*
195 * Table of methods associated with the CertTool class.
196 */
197static JNINativeMethod gCertToolMethods[] = {
198 /* name, signature, funcPtr */
199 {"generateCertificateRequest", "(ILjava/lang/String;)Ljava/lang/String;",
200 (void*)android_security_CertTool_generateCertificateRequest},
Chung-yih Wang699ca3f2009-07-04 22:19:51 +0800201 {"isPkcs12Keystore", "([B)Z",
Chung-yih Wangeec11822009-07-02 00:22:04 +0800202 (void*)android_security_CertTool_isPkcs12Keystore},
Chung-yih Wangc9c119e2009-07-16 19:54:33 +0800203 {"getPkcs12Handle", "([BLjava/lang/String;)I",
204 (void*)android_security_CertTool_getPkcs12Handle},
205 {"getPkcs12Certificate", "(I)Ljava/lang/String;",
206 (void*)android_security_CertTool_getPkcs12Certificate},
207 {"getPkcs12PrivateKey", "(I)Ljava/lang/String;",
208 (void*)android_security_CertTool_getPkcs12PrivateKey},
209 {"popPkcs12CertificateStack", "(I)Ljava/lang/String;",
210 (void*)android_security_CertTool_popPkcs12CertificateStack},
211 {"freePkcs12Handle", "(I)V",
212 (void*)android_security_CertTool_freePkcs12Handle},
Chung-yih Wang699ca3f2009-07-04 22:19:51 +0800213 {"generateX509Certificate", "([B)I",
Chung-yih Wangeec11822009-07-02 00:22:04 +0800214 (void*)android_security_CertTool_generateX509Certificate},
215 {"isCaCertificate", "(I)Z",
216 (void*)android_security_CertTool_isCaCertificate},
217 {"getIssuerDN", "(I)Ljava/lang/String;",
218 (void*)android_security_CertTool_getIssuerDN},
219 {"getCertificateDN", "(I)Ljava/lang/String;",
220 (void*)android_security_CertTool_getCertificateDN},
221 {"getPrivateKeyPEM", "(I)Ljava/lang/String;",
222 (void*)android_security_CertTool_getPrivateKeyPEM},
223 {"freeX509Certificate", "(I)V",
224 (void*)android_security_CertTool_freeX509Certificate},
225};
226
227/*
228 * Register several native methods for one class.
229 */
230static int registerNatives(JNIEnv* env, const char* className,
231 JNINativeMethod* gMethods, int numMethods)
232{
233 jclass clazz;
234
235 clazz = (*env)->FindClass(env, className);
236 if (clazz == NULL) {
237 LOGE("Can not find class %s\n", className);
238 return JNI_FALSE;
239 }
240
241 if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0) {
242 LOGE("Can not RegisterNatives\n");
243 return JNI_FALSE;
244 }
245
246 return JNI_TRUE;
247}
248
249jint JNI_OnLoad(JavaVM* vm, void* reserved)
250{
251 JNIEnv* env = NULL;
252 jint result = -1;
253
254
255 if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
256 goto bail;
257 }
258
259 if (!registerNatives(env, "android/security/CertTool",
260 gCertToolMethods, nelem(gCertToolMethods))) {
261 goto bail;
262 }
263
264 /* success -- return valid version number */
265 result = JNI_VERSION_1_4;
266
267bail:
268 return result;
269}