1// Copyright 2012 Google Inc. All Rights Reserved.
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//     http://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 "polo/util/poloutil.h"
16
17#include <openssl/rand.h>
18
19namespace polo {
20namespace util {
21
22const std::string PoloUtil::BytesToHexString(const uint8_t* bytes,
23                                             size_t length) {
24  // Use OpenSSL BigNum functions to perform the conversion.
25  BIGNUM* bn = BN_bin2bn(bytes, length, NULL);
26  char* hex = BN_bn2hex(bn);
27  std::string hex_string(hex);
28  BN_free(bn);
29  OPENSSL_free(hex);
30  return hex_string;
31}
32
33const size_t PoloUtil::HexStringToBytes(const std::string hex_string,
34                                        uint8_t*& bytes) {
35  // Use OpenSSL BigNum functions to perform the conversion.
36  BIGNUM* bn = NULL;
37  BN_hex2bn(&bn, hex_string.c_str());
38  int length = BN_num_bytes(bn);
39  bytes = new uint8_t[length];
40  BN_bn2bin(bn, &bytes[0]);
41  BN_free(bn);
42  return length;
43}
44
45const void PoloUtil::IntToBigEndianBytes(uint32_t value,
46                                         uint8_t*& bytes) {
47  // Use OpenSSL BigNum functions to perform the conversion.
48  BIGNUM* bn = BN_new();
49  BN_add_word(bn, value);
50
51  // Initialize the array to 0 so there will be leading null bytes if the
52  // number is less than 4 bytes long.
53  bytes = new uint8_t[4];
54  for (int i = 0; i < 4; i++) {
55    bytes[i] = 0;
56  }
57
58  int length = BN_num_bytes(bn);
59  BN_bn2bin(bn, &bytes[4 - length]);
60  BN_free(bn);
61}
62
63const uint32_t PoloUtil::BigEndianBytesToInt(
64    const uint8_t* bytes) {
65  // Use OpenSSL BigNum functions to perform the conversion.
66  BIGNUM* bn = BN_bin2bn(bytes, 4, NULL);
67  BN_ULONG value = bn->d[0];
68  BN_free(bn);
69  return value;
70}
71
72uint8_t* PoloUtil::GenerateRandomBytes(size_t length) {
73  // Use the OpenSSL library to generate the random byte array. The RAND_bytes
74  // function is guaranteed to provide secure random bytes.
75  uint8_t* buffer = new uint8_t[length];
76  if (RAND_bytes(buffer, length)) {
77    return buffer;
78  } else {
79    delete buffer;
80    return NULL;
81  }
82}
83
84}  // namespace util
85}  // namespace polo
86