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