blob: 1ce4d7b502d5cf490dd4ba44bfce462b3ba0ee62 [file] [log] [blame]
// Copyright 2020 Google LLC
//
// 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
//
// https://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 "securegcm/java_util.h"
#include <cstring>
namespace securegcm {
namespace java_util {
namespace {
// Returns the lower 32-bits of a int64_t |value| as an int32_t.
int32_t Lower32Bits(int64_t value) {
const uint32_t lower_bits = static_cast<uint32_t>(value & 0xFFFFFFFF);
int32_t return_value;
std::memcpy(&return_value, &lower_bits, sizeof(uint32_t));
return return_value;
}
} // namespace
int32_t JavaMultiply(int32_t lhs, int32_t rhs) {
// Multiplication guaranteed to fit in int64_t, range from [2^63, 2^63 - 1].
// Minimum value is (-2^31)^2 = 2^62.
const int64_t result = static_cast<int64_t>(lhs) * static_cast<int64_t>(rhs);
return Lower32Bits(result);
}
int32_t JavaAdd(int32_t lhs, int32_t rhs) {
const int64_t result = static_cast<int64_t>(lhs) + static_cast<int64_t>(rhs);
return Lower32Bits(result);
}
int32_t JavaHashCode(const securemessage::ByteBuffer& byte_buffer) {
const string bytes = byte_buffer.String();
int32_t hash_code = 1;
for (const int8_t byte : bytes) {
int32_t int_value = static_cast<int32_t>(byte);
// Java relies on the overflow/underflow behaviour of arithmetic operations,
// which is undefined in C++, so we call our own Java-compatible versions of
// + and * here.
hash_code = JavaAdd(JavaMultiply(31, hash_code), int_value);
}
return hash_code;
}
} // namespace java_util
} // namespace securegcm