1/*
2* Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3*
4* Licensed under the Apache License, Version 2.0 (the "License").
5* You may not use this file except in compliance with the License.
6* A copy of the License is located at
7*
8* http://aws.amazon.com/apache2.0
9*
10* or in the "license" file accompanying this file. This file is distributed
11* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12* express or implied. See the License for the specific language governing
13* permissions and limitations under the License.
14*/
15
16#include <aws/core/utils/UUID.h>
17#include <aws/core/utils/HashingUtils.h>
18#include <aws/core/utils/StringUtils.h>
19#include <aws/core/utils/crypto/Factories.h>
20#include <aws/core/utils/crypto/SecureRandom.h>
21#include <iomanip>
22
23namespace Aws
24{
25 namespace Utils
26 {
27 static const size_t UUID_STR_SIZE = 0x24u; // 36 characters
28 static const size_t VERSION_LOCATION = 0x06u;
29 static const size_t VARIANT_LOCATION = 0x08u;
30 static const unsigned char VERSION = 0x40u;
31 static const unsigned char VERSION_MASK = 0x0Fu;
32 static const unsigned char VARIANT = 0x80u;
33 static const unsigned char VARIANT_MASK = 0x3Fu;
34
35 static void hexify(Aws::String& ss, const unsigned char* toWrite, size_t min, size_t max)
36 {
37 for (size_t i = min; i < max; ++i)
38 {
39 ss.push_back("0123456789ABCDEF"[toWrite[i] >> 4]);
40 ss.push_back("0123456789ABCDEF"[toWrite[i] & 0x0F]);
41 }
42 }
43
44 UUID::UUID(const Aws::String& uuidToConvert)
45 {
46 //GUID has 2 characters per byte + 4 dashes = 36 bytes
47 assert(uuidToConvert.length() == UUID_STR_SIZE);
48 memset(m_uuid, 0, sizeof(m_uuid));
49 Aws::String escapedHexStr(uuidToConvert);
50 StringUtils::Replace(escapedHexStr, "-", "");
51 assert(escapedHexStr.length() == UUID_BINARY_SIZE * 2);
52 ByteBuffer&& rawUuid = HashingUtils::HexDecode(escapedHexStr);
53 memcpy(m_uuid, rawUuid.GetUnderlyingData(), rawUuid.GetLength());
54 }
55
56 UUID::UUID(const unsigned char toCopy[UUID_BINARY_SIZE])
57 {
58 memcpy(m_uuid, toCopy, sizeof(m_uuid));
59 }
60
61 UUID::operator Aws::String() const
62 {
63 Aws::String ss;
64 ss.reserve(UUID_STR_SIZE);
65 hexify(ss, m_uuid, 0, 4);
66 ss.push_back('-');
67
68 hexify(ss, m_uuid, 4, 6);
69 ss.push_back('-');
70
71 hexify(ss, m_uuid, 6, 8);
72 ss.push_back('-');
73
74 hexify(ss, m_uuid, 8, 10);
75 ss.push_back('-');
76
77 hexify(ss, m_uuid, 10, 16);
78
79 return ss;
80 }
81
82 UUID UUID::RandomUUID()
83 {
84 auto secureRandom = Crypto::CreateSecureRandomBytesImplementation();
85 assert(secureRandom);
86
87 unsigned char randomBytes[UUID_BINARY_SIZE];
88 memset(randomBytes, 0, UUID_BINARY_SIZE);
89 secureRandom->GetBytes(randomBytes, UUID_BINARY_SIZE);
90 //Set version bits to 0100
91 //https://tools.ietf.org/html/rfc4122#section-4.1.3
92 randomBytes[VERSION_LOCATION] = (randomBytes[VERSION_LOCATION] & VERSION_MASK) | VERSION;
93 //set variant bits to 10
94 //https://tools.ietf.org/html/rfc4122#section-4.1.1
95 randomBytes[VARIANT_LOCATION] = (randomBytes[VARIANT_LOCATION] & VARIANT_MASK) | VARIANT;
96
97 return UUID(randomBytes);
98 }
99 }
100}
101