1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "securegcm/java_util.h"
16
17 #include <cstring>
18
19 namespace securegcm {
20 namespace java_util {
21
22 namespace {
23
24 // Returns the lower 32-bits of a int64_t |value| as an int32_t.
Lower32Bits(int64_t value)25 int32_t Lower32Bits(int64_t value) {
26 const uint32_t lower_bits = static_cast<uint32_t>(value & 0xFFFFFFFF);
27 int32_t return_value;
28 std::memcpy(&return_value, &lower_bits, sizeof(uint32_t));
29 return return_value;
30 }
31
32 } // namespace
33
JavaMultiply(int32_t lhs,int32_t rhs)34 int32_t JavaMultiply(int32_t lhs, int32_t rhs) {
35 // Multiplication guaranteed to fit in int64_t, range from [2^63, 2^63 - 1].
36 // Minimum value is (-2^31)^2 = 2^62.
37 const int64_t result = static_cast<int64_t>(lhs) * static_cast<int64_t>(rhs);
38 return Lower32Bits(result);
39 }
40
JavaAdd(int32_t lhs,int32_t rhs)41 int32_t JavaAdd(int32_t lhs, int32_t rhs) {
42 const int64_t result = static_cast<int64_t>(lhs) + static_cast<int64_t>(rhs);
43 return Lower32Bits(result);
44 }
45
JavaHashCode(const securemessage::ByteBuffer & byte_buffer)46 int32_t JavaHashCode(const securemessage::ByteBuffer& byte_buffer) {
47 const string bytes = byte_buffer.String();
48 int32_t hash_code = 1;
49 for (const int8_t byte : bytes) {
50 int32_t int_value = static_cast<int32_t>(byte);
51 // Java relies on the overflow/underflow behaviour of arithmetic operations,
52 // which is undefined in C++, so we call our own Java-compatible versions of
53 // + and * here.
54 hash_code = JavaAdd(JavaMultiply(31, hash_code), int_value);
55 }
56 return hash_code;
57 }
58
59 } // namespace java_util
60 } // namespace securegcm
61