summaryrefslogtreecommitdiff
path: root/cpp/src/IceUtil/SHA1.cpp
blob: cfa9d70040b6eca87e5865bbb323a8b0c47a8fca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// **********************************************************************
//
// Copyright (c) 2003-2014 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************

#include <IceUtil/SHA1.h>

#if defined(_WIN32) && !defined(ICE_OS_WINRT)
#   include <IceUtil/Exception.h>
#endif

using namespace std;
using namespace IceUtil;

#ifndef ICE_OS_WINRT
#   if defined(_WIN32)

namespace
{
const int SHA_DIGEST_LENGTH = 20;
}

IceUtil::SHA1::SHA1() :
    _ctx(0),
    _hash(0)
{
    if(!CryptAcquireContext(&_ctx, 0, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
    {
        throw IceUtil::SyscallException(__FILE__, __LINE__, GetLastError());
    }

    if(!CryptCreateHash(_ctx, CALG_SHA1, 0, 0, &_hash))
    {
        throw IceUtil::SyscallException(__FILE__, __LINE__, GetLastError());
    }
}

IceUtil::SHA1::~SHA1()
{
    if(_hash)
    {
        CryptDestroyHash(_hash);
    }

    if(_ctx)
    {
        CryptReleaseContext(_ctx, 0);
    }
}
#   elif defined(__APPLE__)
IceUtil::SHA1::SHA1()
{
    CC_SHA1_Init(&_ctx);
}
#   else
IceUtil::SHA1::SHA1()
{
    SHA1_Init(&_ctx);
}
#   endif

void
IceUtil::SHA1::update(const unsigned char* data, size_t length)
{
#   if defined(_WIN32)
    if(!CryptHashData(_hash, data, static_cast<DWORD>(length), 0))
    {
        throw IceUtil::SyscallException(__FILE__, __LINE__, GetLastError());
    }
#   elif defined(__APPLE__)
    CC_SHA1_Update(&_ctx, reinterpret_cast<const void*>(data), length);
#   else
    SHA1_Update(&_ctx, reinterpret_cast<const void*>(data), length);
#   endif
}

void
IceUtil::SHA1::finalize(vector<unsigned char>& md)
{
#   if defined(_WIN32)
    md.resize(SHA_DIGEST_LENGTH);
    DWORD length = SHA_DIGEST_LENGTH;
    if(!CryptGetHashParam(_hash, HP_HASHVAL, &md[0], &length, 0))
    {
        throw IceUtil::SyscallException(__FILE__, __LINE__, GetLastError());
    }
#   elif defined(__APPLE__)
    md.resize(CC_SHA1_DIGEST_LENGTH);
    CC_SHA1_Final(&md[0], &_ctx);
#   else
    md.resize(SHA_DIGEST_LENGTH);
    SHA1_Final(&md[0], &_ctx);
#   endif
}
#endif

void
IceUtil::sha1(const unsigned char* data, size_t length, vector<unsigned char>& md)
{
#if defined(ICE_OS_WINRT)
    auto dataA =
        ref new Platform::Array<unsigned char>(const_cast<unsigned char*>(data), static_cast<unsigned int>(length));
    auto hasher = Windows::Security::Cryptography::Core::HashAlgorithmProvider::OpenAlgorithm("SHA1");
    auto hashed = hasher->HashData(Windows::Security::Cryptography::CryptographicBuffer::CreateFromByteArray(dataA));
    auto reader = ::Windows::Storage::Streams::DataReader::FromBuffer(hashed);
    md.resize(reader->UnconsumedBufferLength);
    if(!md.empty())
    {
        reader->ReadBytes(::Platform::ArrayReference<unsigned char>(&md[0], static_cast<unsigned int>(md.size())));
    }
#elif defined(_WIN32)
    SHA1 hasher;
    hasher.update(data, length);
    hasher.finalize(md);
#elif defined(__APPLE__)
    md.resize(CC_SHA1_DIGEST_LENGTH);
    CC_SHA1(&data[0], length, &md[0]);
#else
    md.resize(SHA_DIGEST_LENGTH);
    ::SHA1(&data[0], length, &md[0]);
#endif
}