/* * Copyright (C) 2007 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. */ #include <objmng/drm_decoder.h> /* global variables */ static const uint8_t * base64_alphabet = (const uint8_t *)"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; #define SKIP_CRLF(p) while('\r' == *(p) || '\n' == *(p)) \ p++ static int8_t get_alphabet_index(int8_t ch) { uint8_t * tmp; if ('=' == ch) return 64; tmp = (uint8_t *)strchr((const char *)base64_alphabet, ch); if (NULL == tmp) return -1; return (int8_t)(tmp - base64_alphabet); } /* See drm_decoder.h */ int32_t drm_decodeBase64(uint8_t * dest, int32_t destLen, uint8_t * src, int32_t * srcLen) { int32_t maxDestSize, i, maxGroup; uint8_t *pDest, *pSrc; int8_t tpChar; if (NULL == src || NULL == srcLen || *srcLen <= 0 || destLen < 0) return -1; maxDestSize = (*srcLen) * 3/4; if (NULL == dest || 0 == destLen) return maxDestSize; if (destLen < maxDestSize) maxDestSize = destLen; maxGroup = maxDestSize/3; pDest = dest; /* start to decode src to dest */ pSrc = src; for (i = 0; i < maxGroup && *srcLen - (pSrc - src) >= 4; i++) { SKIP_CRLF(pSrc); if (pSrc - src >= *srcLen) break; tpChar = get_alphabet_index(*pSrc); /* to first byte */ if (-1 == tpChar || 64 == tpChar) return -1; pDest[0] = tpChar << 2; pSrc++; SKIP_CRLF(pSrc); tpChar = get_alphabet_index(*pSrc); if (-1 == tpChar || 64 == tpChar) return -1; pDest[0] |= (tpChar >> 4); pDest[1] = tpChar << 4; /* to second byte */ pSrc++; SKIP_CRLF(pSrc); tpChar = get_alphabet_index(*pSrc); if (-1 == tpChar) return -1; if (64 == tpChar) /* end */ return pDest - dest + 1; pDest[1] |= (tpChar >> 2); pDest[2] = tpChar << 6; /* to third byte */ pSrc++; SKIP_CRLF(pSrc); tpChar = get_alphabet_index(*pSrc); if (-1 == tpChar) return -1; if (64 == tpChar) /* end */ return pDest - dest + 2; pDest[2] |= tpChar; pDest += 3; pSrc++; } *srcLen = pSrc - src; return pDest - dest; }