1 /* //device/libs/android_runtime/android_util_Base64.cpp
2 **
3 ** Copyright 2008, 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
18 /*********************************************************
19 *
20 * This code was copied from
21 * system/extra/ssh/dropbear-0.49/libtomcrypt/src/misc/base64/base64_decode.c
22 *
23 *********************************************************/
24
25 #define LOG_TAG "Base64"
26
27 #include <utils/Log.h>
28
29 #include <android_runtime/AndroidRuntime.h>
30
31 #include "JNIHelp.h"
32
33 #include <sys/errno.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <fcntl.h>
37 #include <signal.h>
38
39 namespace android {
40
41 static const unsigned char map[256] = {
42 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
43 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
44 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
45 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
46 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
47 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
48 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
49 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
50 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
51 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
52 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
53 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
54 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
55 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
56 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
57 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
58 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
59 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
60 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
61 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
62 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
63 255, 255, 255, 255 };
64
65 /**
66 base64 decode a block of memory
67 @param in The base64 data to decode
68 @param inlen The length of the base64 data
69 @param out [out] The destination of the binary decoded data
70 @param outlen [in/out] The max size and resulting size of the decoded data
71 @return 0 if successful
72 */
base64_decode(const unsigned char * in,unsigned long inlen,unsigned char * out,unsigned long * outlen)73 int base64_decode(const unsigned char *in, unsigned long inlen,
74 unsigned char *out, unsigned long *outlen)
75 {
76 unsigned long t, x, y, z;
77 unsigned char c;
78 int g;
79
80 g = 3;
81 for (x = y = z = t = 0; x < inlen; x++) {
82 c = map[in[x]&0xFF];
83 if (c == 255) continue;
84 /* the final = symbols are read and used to trim the remaining bytes */
85 if (c == 254) {
86 c = 0;
87 /* prevent g < 0 which would potentially allow an overflow later */
88 if (--g < 0) {
89 return -3;
90 }
91 } else if (g != 3) {
92 /* we only allow = to be at the end */
93 return -4;
94 }
95
96 t = (t<<6)|c;
97
98 if (++y == 4) {
99 if (z + g > *outlen) {
100 return -2;
101 }
102 out[z++] = (unsigned char)((t>>16)&255);
103 if (g > 1) out[z++] = (unsigned char)((t>>8)&255);
104 if (g > 2) out[z++] = (unsigned char)(t&255);
105 y = t = 0;
106 }
107 }
108 if (y != 0) {
109 return -5;
110 }
111 *outlen = z;
112 return 0;
113 }
114
decodeBase64(JNIEnv * env,jobject jobj,jstring jdata)115 static jbyteArray decodeBase64(JNIEnv *env, jobject jobj, jstring jdata)
116 {
117 const char * rawData = env->GetStringUTFChars(jdata, NULL);
118 int stringLength = env->GetStringUTFLength(jdata);
119
120 int resultLength = stringLength / 4 * 3;
121 if (rawData[stringLength-1] == '=') {
122 resultLength -= 1;
123 if (rawData[stringLength-2] == '=') {
124 resultLength -= 1;
125 }
126 }
127
128 jbyteArray byteArray = env->NewByteArray(resultLength);
129 jbyte* byteArrayData = env->GetByteArrayElements(byteArray, NULL);
130
131 unsigned long outlen = resultLength;
132 int result = base64_decode((const unsigned char*)rawData, stringLength, (unsigned char *)byteArrayData, &outlen);
133 if (result != 0)
134 memset((unsigned char *)byteArrayData, -result, resultLength);
135
136 env->ReleaseStringUTFChars(jdata, rawData);
137 env->ReleaseByteArrayElements(byteArray, byteArrayData, 0);
138
139 return byteArray;
140 }
141
142 static const JNINativeMethod methods[] = {
143 {"decodeBase64Native", "(Ljava/lang/String;)[B", (void*)decodeBase64 }
144 };
145
146 static const char* const kBase64PathName = "android/os/Base64Utils";
147
register_android_util_Base64(JNIEnv * env)148 int register_android_util_Base64(JNIEnv* env)
149 {
150 jclass clazz;
151
152 clazz = env->FindClass(kBase64PathName);
153 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Base64Utils");
154
155 return AndroidRuntime::registerNativeMethods(
156 env, kBase64PathName,
157 methods, NELEM(methods));
158 }
159
160 }
161