17c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// Copyright 2012 Google Inc. All Rights Reserved.
27c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet//
37c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// Licensed under the Apache License, Version 2.0 (the "License");
47c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// you may not use this file except in compliance with the License.
57c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// You may obtain a copy of the License at
67c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet//
77c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet//     http://www.apache.org/licenses/LICENSE-2.0
87c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet//
97c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// Unless required by applicable law or agreed to in writing, software
107c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// distributed under the License is distributed on an "AS IS" BASIS,
117c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// See the License for the specific language governing permissions and
137c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet// limitations under the License.
147c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
157c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet#include "polo/util/poloutil.h"
167c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
177c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet#include <openssl/rand.h>
187c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
197c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetnamespace polo {
207c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetnamespace util {
217c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
227c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetconst std::string PoloUtil::BytesToHexString(const uint8_t* bytes,
237c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet                                             size_t length) {
247c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  // Use OpenSSL BigNum functions to perform the conversion.
257c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BIGNUM* bn = BN_bin2bn(bytes, length, NULL);
267c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  char* hex = BN_bn2hex(bn);
277c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  std::string hex_string(hex);
287c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BN_free(bn);
297c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  OPENSSL_free(hex);
307c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  return hex_string;
317c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
327c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
337c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetconst size_t PoloUtil::HexStringToBytes(const std::string hex_string,
347c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet                                        uint8_t*& bytes) {
357c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  // Use OpenSSL BigNum functions to perform the conversion.
367c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BIGNUM* bn = NULL;
377c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BN_hex2bn(&bn, hex_string.c_str());
387c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  int length = BN_num_bytes(bn);
397c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  bytes = new uint8_t[length];
407c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BN_bn2bin(bn, &bytes[0]);
417c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BN_free(bn);
427c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  return length;
437c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
447c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
457c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetconst void PoloUtil::IntToBigEndianBytes(uint32_t value,
467c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet                                         uint8_t*& bytes) {
477c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  // Use OpenSSL BigNum functions to perform the conversion.
487c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BIGNUM* bn = BN_new();
497c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BN_add_word(bn, value);
507c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
517c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  // Initialize the array to 0 so there will be leading null bytes if the
527c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  // number is less than 4 bytes long.
537c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  bytes = new uint8_t[4];
547c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  for (int i = 0; i < 4; i++) {
557c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    bytes[i] = 0;
567c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
577c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
587c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  int length = BN_num_bytes(bn);
597c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BN_bn2bin(bn, &bytes[4 - length]);
607c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BN_free(bn);
617c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
627c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
637c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetconst uint32_t PoloUtil::BigEndianBytesToInt(
647c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    const uint8_t* bytes) {
657c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  // Use OpenSSL BigNum functions to perform the conversion.
667c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BIGNUM* bn = BN_bin2bn(bytes, 4, NULL);
677c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BN_ULONG value = bn->d[0];
687c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  BN_free(bn);
697c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  return value;
707c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
717c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
727c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichetuint8_t* PoloUtil::GenerateRandomBytes(size_t length) {
737c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  // Use the OpenSSL library to generate the random byte array. The RAND_bytes
747c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  // function is guaranteed to provide secure random bytes.
757c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  uint8_t* buffer = new uint8_t[length];
767c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  if (RAND_bytes(buffer, length)) {
777c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return buffer;
787c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  } else {
797c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    delete buffer;
807c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet    return NULL;
817c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet  }
827c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}
837c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet
847c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}  // namespace util
857c9978567a202d6aa98beac5da5e1b3b34792862Jerome Poichet}  // namespace polo
86