blob: bc69747c1bcfe28be84fc2c1db4670aa414c5361 [file] [log] [blame]
/* //device/libs/android_runtime/android_util_Base64.cpp
**
** Copyright 2008, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
/*********************************************************
*
* This code was copied from
* system/extra/ssh/dropbear-0.49/libtomcrypt/src/misc/base64/base64_decode.c
*
*********************************************************/
#define LOG_TAG "Base64"
#include <utils/Log.h>
#include <android_runtime/AndroidRuntime.h>
#include "JNIHelp.h"
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
namespace android {
static const unsigned char map[256] = {
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255 };
/**
base64 decode a block of memory
@param in The base64 data to decode
@param inlen The length of the base64 data
@param out [out] The destination of the binary decoded data
@param outlen [in/out] The max size and resulting size of the decoded data
@return 0 if successful
*/
int base64_decode(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long t, x, y, z;
unsigned char c;
int g;
g = 3;
for (x = y = z = t = 0; x < inlen; x++) {
c = map[in[x]&0xFF];
if (c == 255) continue;
/* the final = symbols are read and used to trim the remaining bytes */
if (c == 254) {
c = 0;
/* prevent g < 0 which would potentially allow an overflow later */
if (--g < 0) {
return -3;
}
} else if (g != 3) {
/* we only allow = to be at the end */
return -4;
}
t = (t<<6)|c;
if (++y == 4) {
if (z + g > *outlen) {
return -2;
}
out[z++] = (unsigned char)((t>>16)&255);
if (g > 1) out[z++] = (unsigned char)((t>>8)&255);
if (g > 2) out[z++] = (unsigned char)(t&255);
y = t = 0;
}
}
if (y != 0) {
return -5;
}
*outlen = z;
return 0;
}
static jbyteArray decodeBase64(JNIEnv *env, jobject jobj, jstring jdata)
{
const char * rawData = env->GetStringUTFChars(jdata, NULL);
int stringLength = env->GetStringUTFLength(jdata);
int resultLength = stringLength / 4 * 3;
if (rawData[stringLength-1] == '=') {
resultLength -= 1;
if (rawData[stringLength-2] == '=') {
resultLength -= 1;
}
}
jbyteArray byteArray = env->NewByteArray(resultLength);
jbyte* byteArrayData = env->GetByteArrayElements(byteArray, NULL);
unsigned long outlen = resultLength;
int result = base64_decode((const unsigned char*)rawData, stringLength, (unsigned char *)byteArrayData, &outlen);
if (result != 0)
memset((unsigned char *)byteArrayData, -result, resultLength);
env->ReleaseStringUTFChars(jdata, rawData);
env->ReleaseByteArrayElements(byteArray, byteArrayData, 0);
return byteArray;
}
static const JNINativeMethod methods[] = {
{"decodeBase64Native", "(Ljava/lang/String;)[B", (void*)decodeBase64 }
};
static const char* const kBase64PathName = "android/os/Base64Utils";
int register_android_util_Base64(JNIEnv* env)
{
jclass clazz;
clazz = env->FindClass(kBase64PathName);
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Base64Utils");
return AndroidRuntime::registerNativeMethods(
env, kBase64PathName,
methods, NELEM(methods));
}
}