1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26/**
27 * \file KMSAgentChallenge.cpp
28 */
29
30#include "KMSAgentChallenge.h"
31#include "KMSAgentCryptoUtilities.h"
32#include "KMSAgentStringUtilities.h"
33#include "ApplianceParameters.h"
34#include "SYSCommon.h"
35
36extern "C" int Log2(char* msg1,
37                    char* msg2);
38
39#ifdef METAWARE
40#include "debug.h"
41#endif
42
43
44/**
45 *  ComputeChallengeResponse
46 */
47bool ComputeChallengeResponse(
48   const unsigned char* i_pAuthenticationSecret,
49   int i_iAuthenticationSecretLength,
50   const unsigned char* i_pRootCACertificate,
51   int i_iRootCACertificateLength,
52   const unsigned char* i_pAuthenticationChallenge,
53   int i_iAuthenticationChallengeLength,
54   unsigned char* o_pAuthenticationChallengeResponse,
55   int i_iAuthenticationChallengeResponseLength )
56{
57
58   bool rc;
59
60#ifdef DEBUG
61   Log2 ("KMSAgent_LoadProfile::ComputeChallengeResponse", "Entered");
62#endif
63   FATAL_ASSERT( i_iAuthenticationChallengeResponseLength == HMAC_LENGTH );
64
65   // challenge response is HMAC-SHA1( RootCACertificate ||
66   // AuthenticationChallenge, AuthenticationSecret )
67   const unsigned char* aBuffersToHMAC[2];
68   int aBuffersToHMACSize[2];
69
70   aBuffersToHMAC[0]     = i_pRootCACertificate;
71   aBuffersToHMACSize[0] = i_iRootCACertificateLength;
72
73   aBuffersToHMAC[1]     = i_pAuthenticationChallenge;
74   aBuffersToHMACSize[1] = i_iAuthenticationChallengeLength;
75
76   rc = HMACBuffers(
77      2,
78      aBuffersToHMAC,
79      aBuffersToHMACSize,
80      i_pAuthenticationSecret,
81      i_iAuthenticationSecretLength,
82      o_pAuthenticationChallengeResponse );
83
84#if defined(METAWARE) && defined(DEBUG)
85   int j=0;
86
87   j+=snprintf(outmsg+j, OUTMSG_SIZE,
88              "length=%x\n",
89              i_iAuthenticationSecretLength);
90
91   for (int i=0 ; i< i_iAuthenticationSecretLength; i++)
92   {
93      j+=snprintf(outmsg+j,  OUTMSG_SIZE,
94                 "%x",
95                 i_pAuthenticationSecret[i]);
96   }
97   snprintf(outmsg+j,  OUTMSG_SIZE, "\n");
98
99   Log2("Secret = ",outmsg);
100#endif
101
102#if defined(METAWARE) && defined(DEBUG)
103   j=0;
104
105   j+=snprintf(outmsg+j,  OUTMSG_SIZE,
106              "length=%x\n",
107              i_iRootCACertificateLength);
108
109   for (i=0 ; i< i_iRootCACertificateLength; i++)
110   {
111      j+=snprintf(outmsg+j,  OUTMSG_SIZE,
112                 "%x",
113                 i_pRootCACertificate[i]);
114   }
115   snprintf(outmsg+j, OUTMSG_SIZE, "\n");
116
117   Log2("i_pRootCACertificate = ",outmsg);
118#endif
119
120#if defined(METAWARE) && defined(DEBUG)
121   j=0;
122
123   j+=snprintf(outmsg+j,  OUTMSG_SIZE,
124              "length=%x\n",
125              i_iAuthenticationChallengeLength);
126
127   for (i=0 ; i< i_iAuthenticationChallengeLength; i++)
128   {
129      j+=snprintf(outmsg+j,  OUTMSG_SIZE,
130                 "%x",
131                 i_pAuthenticationChallenge[i]);
132   }
133   snprintf(outmsg+j,  OUTMSG_SIZE, "\n");
134
135   Log2("i_pAuthenticationChallenge = ",outmsg);
136#endif
137
138#if defined(METAWARE) && defined(DEBUG)
139   j=0;
140
141   j+=snprintf(outmsg+j,  OUTMSG_SIZE,
142              "length=%x\n",
143              i_iAuthenticationChallengeResponseLength);
144
145   for (i=0 ; i< i_iAuthenticationChallengeResponseLength; i++)
146   {
147      j+=snprintf(outmsg+j,  OUTMSG_SIZE,
148                 "%x",
149                 o_pAuthenticationChallengeResponse[i]);
150   }
151   snprintf(outmsg+j,  OUTMSG_SIZE, "\n");
152
153   Log2("o_pAuthenticationChallengeResponse = ",outmsg);
154#endif
155
156   return rc;
157
158#undef __IAM__
159}
160
161/**
162 *   ComputeEntityHashedPassphraseAndAuthenticationSecret
163 */
164bool ComputeEntityHashedPassphraseAndAuthenticationSecret(
165        const char* i_sPassphrase,
166        char* const o_sHexHashedPassphrase,
167        int* const  o_piAuthenticationHashIterationCount,
168        char* const o_sHexAuthenticationSecret )
169{
170    // HashedPassphrase is SHA1( Passphrase-UTF-8 )
171    // Using UTF-8 ensures the same result on different platforms with
172    // different wide character representations.
173    // This hashed passphrase value is used to wrap entity
174    // private key materials.
175#if defined(METAWARE) && defined(DEBUG)
176    Log2 ("KMSAgent_LoadProfile::ComputeEntityHashedPassphraseAndAuthenticationSecret",
177          "Entered");
178#endif
179
180    unsigned char aHashedPassphrase[HASH_LENGTH];
181
182    memset(aHashedPassphrase, 0, HASH_LENGTH);
183
184    if ( strlen(i_sPassphrase) > 0 )
185    {
186        if ( !HashBuffer(
187                    (unsigned char*)i_sPassphrase,
188                    strlen(i_sPassphrase),
189                    aHashedPassphrase) )
190        {
191            return false;
192        }
193    }
194
195    ConvertBinaryToUTF8HexString( o_sHexHashedPassphrase,
196                                  aHashedPassphrase,
197                                  HASH_LENGTH );
198
199    // HexAuthenticationSecret is SHA1( SHA1( ... ( SHA1(
200    // HashedPassphrase ) ) ) The number of iterations is time bounded
201    // at 1/10 of a second, and also bounded by fixed minimum and
202    // maximum values (to prevent too weak of a computation and to
203    // prevent a DoS, respectively).  This value is used as the shared
204    // secret in challenge-response authentication exchanges.
205
206    *o_piAuthenticationHashIterationCount = 0;
207
208    unsigned long iStartTickCount = K_GetTickCount();
209
210    while ( *o_piAuthenticationHashIterationCount <
211            MAX_AUTHENTICATION_ITERATION_COUNT
212            && ( *o_piAuthenticationHashIterationCount <
213                 MIN_AUTHENTICATION_ITERATION_COUNT
214                 || iStartTickCount +
215                 AUTHENTICATION_ITERATION_TIME_IN_MILLISECONDS >
216                 K_GetTickCount() ) )
217    {
218       if ( !HashBuffer(
219               aHashedPassphrase,
220               HASH_LENGTH,
221               aHashedPassphrase) )
222       {
223          return false;
224       }
225
226       (*o_piAuthenticationHashIterationCount)++;
227    }
228
229    ConvertBinaryToUTF8HexString( o_sHexAuthenticationSecret,
230                                  aHashedPassphrase, HASH_LENGTH );
231
232#if defined(METAWARE) && defined(DEBUG)
233    snprintf(outmsg,  OUTMSG_SIZE,
234            "o_sHexAuthenticationSecret=%x o_piAuth..."
235            "= %x aHashedPassphrase=%s\n",
236            o_sHexAuthenticationSecret,
237            *o_piAuthenticationHashIterationCount,
238            aHashedPassphrase);
239    Log2("ComputeEntityHashedPassphraseAndAuthenticationSecret ",
240         outmsg);
241#endif
242
243    return true;
244}
245
246/**
247 *   ComputeFixedEntityHashedPassphraseAndAuthenticationSecret
248 */
249bool ComputeFixedEntityHashedPassphraseAndAuthenticationSecret(
250   const char* i_sPassphrase,
251   char* const o_sHexHashedPassphrase,
252   int         i_iAuthenticationHashIterationCount,
253   char* const o_sHexAuthenticationSecret )
254{
255   // compute same values as
256   // ComputeEntityHashedPassphraseAndAuthenticationSecret, except
257   // iteration count is fixed
258#if defined(METAWARE) && defined(DEBUG)
259    Log2 ("KMSAgent_LoadProfile::"
260          "ComputeFixedEntityHashedPassphraseAndAuthenticationSecret", "Entered");
261#endif
262
263   // detect attempts to cause weak computation or DoS attack
264   if ( i_iAuthenticationHashIterationCount <
265        MIN_AUTHENTICATION_ITERATION_COUNT   ||
266        i_iAuthenticationHashIterationCount >
267        MAX_AUTHENTICATION_ITERATION_COUNT )
268   {
269      return false;
270   }
271
272
273   unsigned char aHashedPassphrase[HASH_LENGTH];
274
275   memset(aHashedPassphrase, 0, HASH_LENGTH);
276
277   if ( strlen(i_sPassphrase) > 0 )
278   {
279      if ( !HashBuffer(
280              (unsigned char*)i_sPassphrase,
281              strlen(i_sPassphrase),
282              aHashedPassphrase) )
283      {
284         return false;
285      }
286   }
287
288   ConvertBinaryToUTF8HexString( o_sHexHashedPassphrase,
289                                 aHashedPassphrase, HASH_LENGTH );
290
291   int i;
292   for ( i = 0; i < i_iAuthenticationHashIterationCount; i++ )
293   {
294      if ( !HashBuffer(
295              aHashedPassphrase,
296              HASH_LENGTH,
297              aHashedPassphrase) )
298      {
299         return false;
300      }
301   }
302
303   ConvertBinaryToUTF8HexString( o_sHexAuthenticationSecret,
304                                 aHashedPassphrase, HASH_LENGTH );
305
306#if defined(METAWARE) && defined(DEBUG)
307    snprintf(outmsg,  OUTMSG_SIZE,
308            "i_iAuth %x \n",
309            i_iAuthenticationHashIterationCount);
310
311    Log2("ComputeEntityHashedPassphraseAndAuthenticationSecret ",
312         outmsg);
313#endif
314
315
316   return true;
317}
318