blob: b22fccfeee50751e5f7af3117656127c777d45e0 [file] [log] [blame]
// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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 "starboard/configuration.h"
#include "starboard/cryptography.h"
#include "starboard/shared/starboard/cryptography/cryptography_internal.h"
#include "starboard/shared/starboard/cryptography/software_aes.h"
using starboard::shared::starboard::cryptography::AES_cbc_encrypt;
using starboard::shared::starboard::cryptography::AES_ctr128_encrypt;
using starboard::shared::starboard::cryptography::AES_decrypt;
using starboard::shared::starboard::cryptography::AES_encrypt;
using starboard::shared::starboard::cryptography::AES_gcm128_decrypt;
using starboard::shared::starboard::cryptography::AES_gcm128_encrypt;
using starboard::shared::starboard::cryptography::kAlgorithmAes128Cbc;
using starboard::shared::starboard::cryptography::kAlgorithmAes128Ctr;
using starboard::shared::starboard::cryptography::kAlgorithmAes128Ecb;
using starboard::shared::starboard::cryptography::kAlgorithmAes128Gcm;
namespace {
inline void* AddPtr(void* pointer, int value) {
return reinterpret_cast<char*>(pointer) + value;
}
inline const void* AddPtr(const void* pointer, int value) {
return reinterpret_cast<const char*>(pointer) + value;
}
} // namespace
int SbCryptographyTransform(SbCryptographyTransformer transformer,
const void* in_data,
int in_data_size,
void* out_data) {
if (!SbCryptographyIsTransformerValid(transformer) || !in_data || !out_data) {
return -1;
}
if (in_data_size == 0) {
return 0;
}
switch (transformer->algorithm) {
case kAlgorithmAes128Cbc:
AES_cbc_encrypt(in_data, out_data, in_data_size, &(transformer->key),
transformer->ivec,
transformer->direction == kSbCryptographyDirectionEncode ?
SB_AES_ENCRYPT : SB_AES_DECRYPT);
break;
case kAlgorithmAes128Ctr:
AES_ctr128_encrypt(in_data, out_data, in_data_size, &(transformer->key),
transformer->ivec, transformer->ecount_buf,
&transformer->counter);
break;
case kAlgorithmAes128Ecb:
if (in_data_size % 16 != 0) {
SB_DLOG(ERROR) << "ECB called with a non-multiple of the block size.";
return -1;
}
if (transformer->direction == kSbCryptographyDirectionEncode) {
const void* in = in_data;
void* out = out_data;
for (int i = 0, blocks = in_data_size / 16; i < blocks; ++i) {
AES_encrypt(in, out, &transformer->key);
in = AddPtr(in, 16);
out = AddPtr(out, 16);
}
} else if (transformer->direction == kSbCryptographyDirectionDecode) {
const void* in = in_data;
void* out = out_data;
for (int i = 0, blocks = in_data_size / 16; i < blocks; ++i) {
AES_decrypt(in, out, &transformer->key);
in = AddPtr(in, 16);
out = AddPtr(out, 16);
}
} else {
SB_NOTREACHED();
}
break;
case kAlgorithmAes128Gcm:
if (transformer->direction == kSbCryptographyDirectionEncode) {
AES_gcm128_encrypt(&transformer->gcm_context, &transformer->key,
in_data, out_data, in_data_size);
} else if (transformer->direction == kSbCryptographyDirectionDecode) {
AES_gcm128_decrypt(&transformer->gcm_context, &transformer->key,
in_data, out_data, in_data_size);
} else {
SB_NOTREACHED();
}
break;
default:
SB_NOTREACHED();
return -1;
}
return in_data_size;
}