cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
suiteb.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib Suite B Test Routines *
4 * Copyright Peter Gutmann 2009-2011 *
5 * *
6 ****************************************************************************/
7 
9 //#define CONFIG_SUITEB_TESTS
11 
12 #include <ctype.h> /* For arg-parsing */
13 #include "cryptlib.h"
14 #include "test/test.h"
15 
16 #if defined( __MVS__ ) || defined( __VMCMS__ )
17  /* Suspend conversion of literals to ASCII. */
18  #pragma convlit( suspend )
19 #endif /* IBM big iron */
20 #if defined( __ILEC400__ )
21  #pragma convert( 0 )
22 #endif /* IBM medium iron */
23 
24 #ifdef CONFIG_SUITEB_TESTS
25 
26 /* Test-specific flags to control details of each test */
27 
28 #define TESTFLAG_SENDHTTPREQ 0x01 /* Send HTTP req.over TLS link */
29 #define TESTFLAG_GENERIC 0x02 /* Don't print "A.x.y.z" for test */
30 
31 /* Special kludge function in cryptapi.c to enable nonstandard behaviour for
32  Suite B tests. The definitions below are copined from session/ssl.h */
33 
34 typedef enum {
35  SUITEB_TEST_NONE, /* No special test behaviour */
36  SUITEB_TEST_CLIINVALIDCURVE,/* Client sends non-Suite B curve */
37  SUITEB_TEST_SVRINVALIDCURVE,/* Server sends non-Suite B curve */
38  SUITEB_TEST_BOTHCURVES, /* Client must send P256 and P384 as supp.curves */
39  SUITEB_TEST_BOTHSIGALGOS, /* Client must send SHA256 and SHA384 as sig.algos */
40  SUITEB_TEST_LAST
41  } SUITEB_TEST_VALUE;
42 
43 C_RET cryptSuiteBTestConfig( C_IN int magicValue );
44 
45 /****************************************************************************
46 * *
47 * Suite B Test Definitions *
48 * *
49 ****************************************************************************/
50 
51 /* Defines to make the table entries smaller and/or easier to understand */
52 
53 #define SECLVL_128 CRYPT_SSLOPTION_SUITEB_128
54 #define SECLVL_256 CRYPT_SSLOPTION_SUITEB_256
55 #define SECLVL_BOTH SECLVL_128 /* For 5430bis, "128" now imples "128+256" */
56 #define FORCE_TLS12 CRYPT_SSLOPTION_MINVER_TLS12
57 
58 #define P521 521 /* For invalid-curve tests */
59 #define P384 384
60 #define P256 256
61 
62 /* Some entries are aliases for other entries, to make this easier to
63  specify we use the following define to fill in the unused fields */
64 
65 #define ALIAS 0, 0, 0, 0, 0, 0
66 #define ALIAS_SPECIAL 0, 0, 0, 0, 0
67 
68 /* Special-case handling situations */
69 
70 typedef enum {
71  SPECIAL_NONE,
72 
73  /* Client tests */
74  /* Client must reject invalid curve (in the form of server key) from server */
75  SPECIAL_SVR_INVALIDCURVE,
76  /* Client must send sig_algo extensions for both P256 and P384 curves */
77  SPECIAL_BOTH_SIGALGO,
78  /* Client must send supported_curves extension for both P256 and P384
79  curves */
80  SPECIAL_BOTH_SUPPCURVES,
81  /* Client/server must send TLS alert due to protocol violation */
82  SPECIAL_CLI_TLSALERT,
83  SPECIAL_SVR_TLSALERT,
84 
85  /* Server tests */
86  /* Server must reject invalid supported-elliptic-curve ext.from client */
87  SPECIAL_CLI_INVALIDCURVE,
88  /* Server must send supported_sig_algo ext for both P256 and P384 */
89  SPECIAL_BOTH_SUPPALGO,
90  SPECIAL_LAST
91  } SPECIAL_HANDLING_TYPE;
92 
93 /* A table that defines the conditions for the various tests. Note that
94  some of the test requirements are handled internally by cryptlib so
95  they're not explicitly tested here, as a result some of the entries may
96  appear to be duplicates */
97 
98 typedef struct {
99  const char *testName;
100 
101  const int clientOptions;
102  const int clientAuthKeySizeBits; /* 0 = no client auth.used */
103 
104  const int serverOptions;
105  const int serverKeySizeBits;
106 
107  const BOOLEAN result;
108  const SPECIAL_HANDLING_TYPE handlingType;
109 
110  const char *aliasTestName;
111  } SUITEB_TEST_INFO;
112 
113 static const SUITEB_TEST_INFO clientTestInfo[] = {
114  { NULL, 0, 0, 0, 0, 0 },
115  /* ------------------------------- Client Tests ------------------------------- */
116  /* Test Client parm Client key Server parm Server key Result Special */
117  /* ---- ----------- ---------- ----------- ---------- ------ ------- */
118 /* 1*/ { "A.1.1.1", SECLVL_128, 0, SECLVL_128, P256, TRUE },
119 /* 2*/ { "A.1.1.2", SECLVL_128, 0, SECLVL_128, P521, FALSE, SPECIAL_SVR_INVALIDCURVE },
120 /* 3*/ { "A.1.2.1", SECLVL_256, 0, SECLVL_256, P384, TRUE },
121 /* 4*/ { "A.1.2.2", SECLVL_256, 0, SECLVL_256, P521, FALSE, SPECIAL_SVR_INVALIDCURVE },
122 /* 5*/ { "A.1.3.1", ALIAS, "A.1.1.1" },
123 /* 6*/ { "A.1.4.1", ALIAS, "A.1.1.1" },
124 /* 7*/ { "A.1.5.1", ALIAS_SPECIAL, SPECIAL_CLI_TLSALERT, "A.1.1.2" },
125 /* 8*/ { "A.1.5.2", ALIAS_SPECIAL, SPECIAL_CLI_TLSALERT, "A.1.2.2" },
126 /* 9*/ { "A.1.6.1", ALIAS, "A.1.4.1" },
127 /*10*/ { "A.1.7.1", SECLVL_128, P256, SECLVL_BOTH, P384, TRUE },
128 /*11*/ { "A.1.7.2", SECLVL_BOTH, P384, SECLVL_128, P256, TRUE },
129 /*12*/ { "A.1.8.1", ALIAS, "A.1.1.1" },
130 /*13*/ { "A.1.9.1", SECLVL_128, 0, SECLVL_BOTH, P384, TRUE },
131 /*14*/ { "A.1.10.1", ALIAS, "A.1.2.1" },
132 /*15*/ { "A.1.11.1", ALIAS, "A.1.2.1" },
133 /*16*/ { "A.1.12.1", ALIAS, "A.1.1.1" },
134 /*17*/ { "A.1.13.1", SECLVL_128, 0, SECLVL_128 | FORCE_TLS12, P256, TRUE },
135 /*18*/ { "A.1.14.1", SECLVL_128, 0, SECLVL_128, P256, TRUE },
136 /*19*/ { "A.1.15.1", SECLVL_128, 0, SECLVL_128, P256, TRUE },
137 /*20*/ { "A.1.16.1", SECLVL_256, 0, SECLVL_256, P384, TRUE },
138 /*21*/ { "A.1.17.1", ALIAS, "A.1.14.1" },
139 /*22*/ { "A.1.18.1", ALIAS, "A.1.14.1" },
140 /*23*/ { "A.1.19.1", ALIAS, "A.1.1.1" },
141 /*24*/ { "A.1.20.1", ALIAS, "A.1.1.1" },
142 /*25*/ { "A.1.21.1", ALIAS, "A.1.2.1" },
143 /*26*/ { "A.1.22.1", ALIAS, "A.1.1.1" },
144 /*27*/ { "A.1.21.2", ALIAS, "A.1.2.1" },
145 /*28*/ { "A.1.24.1", SECLVL_128, 0, SECLVL_128, P256, TRUE },
146 /*29*/ { "A.1.24.2", SECLVL_256, 0, SECLVL_256, P384, TRUE },
147 /*30*/ { "A.1.25.1", ALIAS, "A.1.24.1" },
148 /*31*/ { "A.1.26.1", SECLVL_128, 0, SECLVL_128, P384, TRUE, SPECIAL_BOTH_SUPPCURVES },
149 /*32*/ { "A.1.27.1", ALIAS, "A.1.24.2" },
150 /*33*/ { "A.1.28.1", ALIAS, "A.1.1.1" },
151 /*34*/ { "A.1.29.1", ALIAS, "A.2.8.1" }, // Wrong, should be an A.1.x ref.
152 /*35*/ { "A.1.30.1", ALIAS, "A.1.2.1" },
153 /*36*/ { "A.1.31.1", ALIAS, "A.1.1.1" },
154 /*37*/ { "A.1.32.1", ALIAS, "A.1.1.1" },
155 /*38*/ { "A.1.33.1", ALIAS, "A.1.7.1" },
156 /*39*/ { "A.1.34.1", SECLVL_128, 0, SECLVL_128, P256, TRUE },
157 /*40*/ { "A.1.34.2", SECLVL_256, 0, SECLVL_256, P384, TRUE },
158 /*41*/ { "A.1.35.1", ALIAS, "A.1.34.1" },
159 /*42*/ { "A.1.36.1", SECLVL_BOTH, 0, SECLVL_BOTH, P384, TRUE, SPECIAL_BOTH_SIGALGO },
160 /*43*/ { "A.1.37.1", ALIAS, "A.1.34.2" },
161 /*44*/ { "A.1.39.1", SECLVL_128, P256, SECLVL_128, P256, TRUE },
162 /*45*/ { "A.1.39.2", SECLVL_256, P384, SECLVL_256, P384, TRUE },
163 /*46*/ { "A.1.40.1", ALIAS, "A.1.39.1" },
164 /*47*/ { "A.1.41.1", ALIAS, "A.1.39.2" },
165  /* ---- ----------- ---------- ----------- ---------- ------ ------- */
166  /* Test Client parm Client key Server parm Server key Result Special */
167  /* ------------------------------- Client Tests ------------------------------- */
168  { NULL }, { NULL }
169  };
170 
171 static const SUITEB_TEST_INFO serverTestInfo[] = {
172  { NULL, 0, 0, 0, 0, 0 },
173  /* ------------------------------- Server Tests ------------------------------- */
174  /* Test Client parm Client key Server parm Server key Result Special */
175  /* ---- ----------- ---------- ----------- ---------- ------ ------- */
176 /* 1*/ { "A.2.1.1", SECLVL_128, 0, SECLVL_128, P256, TRUE },
177 /* 2*/ { "A.2.1.2", SECLVL_256, 0, SECLVL_128, P256, FALSE, SPECIAL_CLI_INVALIDCURVE },
178 /* 3*/ { "A.2.2.1", SECLVL_256, 0, SECLVL_256, P384, TRUE },
179 /* 4*/ { "A.2.2.2", SECLVL_256, 0, SECLVL_256, P384, FALSE, SPECIAL_CLI_INVALIDCURVE },
180 /* 5*/ { "A.2.5.1", ALIAS, "A.2.1.2" },
181 /* 6*/ { "A.2.5.1", ALIAS, "A.2.2.2" },
182 /* 7*/ { "A.2.3.1", ALIAS_SPECIAL, SPECIAL_SVR_TLSALERT, "A.2.1.2" },
183 /* 8*/ { "A.2.4.1", ALIAS_SPECIAL, SPECIAL_SVR_TLSALERT, "A.2.2.2" },
184 /* 9*/ { "A.2.6.1", SECLVL_128, P384, SECLVL_BOTH, P256, TRUE },
185 /*10*/ { "A.2.6.2", SECLVL_128, P256, SECLVL_BOTH, P384, TRUE },
186 /*11*/ { "A.2.7.1", ALIAS, "A.2.1.1" },
187 /*12*/ { "A.2.8.1", SECLVL_128, P384, SECLVL_BOTH, P256, TRUE },
188 /*13*/ { "A.2.9.1", ALIAS, "A.2.2.1" },
189 /*14*/ { "A.2.10.1", ALIAS, "A.2.2.1" },
190 /*15*/ { "A.2.11.1", ALIAS, "A.2.6.1" },
191 /*16*/ { "A.2.12.1", SECLVL_128 | FORCE_TLS12, 0, SECLVL_128, P256, TRUE },
192 /*17*/ { "A.2.13.1", SECLVL_BOTH, 0, SECLVL_128, P256, TRUE },
193 /*18*/ { "A.2.14.1", SECLVL_256, 0, SECLVL_256, P384, TRUE },
194 /*19*/ { "A.2.15.1", ALIAS, "A.2.1.1" },
195 /*20*/ { "A.2.16.1", ALIAS, "A.2.1.1" },
196 /*21*/ { "A.2.17.1", ALIAS, "A.2.2.1" },
197 /*22*/ { "A.2.18.1", ALIAS, "A.2.1.1" },
198 /*23*/ { "A.2.18.2", ALIAS, "A.2.2.1" },
199 /*24*/ { "A.2.20.1", ALIAS, "A.2.1.1" },
200 /*25*/ { "A.2.21.1", ALIAS, "A.2.8.1" },
201 /*26*/ { "A.2.22.1", ALIAS, "A.2.2.1" },
202 /*27*/ { "A.2.23.1", SECLVL_128, 0, SECLVL_BOTH, P256, FALSE, SPECIAL_CLI_INVALIDCURVE },
203 /*28*/ { "A.2.24.1", ALIAS_SPECIAL, SPECIAL_SVR_TLSALERT, "A.2.23.1" },
204 /*29*/ { "A.2.26.1", SECLVL_128, P256, SECLVL_128, P256, TRUE },
205 /*30*/ { "A.2.26.2", SECLVL_256, P384, SECLVL_256, P384, TRUE },
206 /*31*/ { "A.2.27.1", ALIAS, "A.2.26.1" },
207 /*32*/ { "A.2.28.1", SECLVL_BOTH, P256, SECLVL_BOTH, P256, TRUE, SPECIAL_BOTH_SUPPALGO },
208 /*33*/ { "A.2.29.1", ALIAS, "A.2.26.2" },
209 /*34*/ { "A.2.30.1", ALIAS, "A.2.1.1" },
210 /*35*/ { "A.2.30.2", ALIAS, "A.2.1.2" },
211 /*36*/ { "A.2.31.1", ALIAS, "A.2.30.1" },
212 /*37*/ { "A.2.32.1", ALIAS, "A.2.30.1" },
213 /*38*/ { "A.2.33.1", ALIAS, "A.2.30.2" },
214  /* ---- ----------- ---------- ----------- ---------- ------ ------- */
215  /* Test Client parm Client key Server parm Server key Result Special */
216  /* ------------------------------- Server Tests ------------------------------- */
217 
218  { NULL }, { NULL }
219  };
220 
221 #define SUITEB_FIRST_CLIENT 1
222 #define SUITEB_LAST_CLIENT 48
223 #define SUITEB_FIRST_SERVER 1
224 #define SUITEB_LAST_SERVER 38
225 
226 /* Display the test numbers and their corresponding test names */
227 
228 static int showTest( const SUITEB_TEST_INFO *testInfoPtr )
229  {
230  int i;
231 
232  for( i = 0; i < 6; i++ )
233  {
234  if( testInfoPtr->testName == NULL )
235  return( FALSE );
236  printf( " %8s", testInfoPtr->testName );
237  testInfoPtr++;
238  }
239  putchar( '\n' );
240 
241  return( TRUE );
242  }
243 
244 static void showTestInfo( void )
245  {
246  int i;
247 
248  puts( " Suite B client tests:" );
249  for( i = 1; clientTestInfo[ i ].testName != NULL; i += 6 )
250  {
251  if( !showTest( &clientTestInfo[ i ] ) )
252  {
253  printf( "\n" );
254  break;
255  }
256  }
257  puts( "\n Suite B server tests:" );
258  for( i = 1; serverTestInfo[ i ].testName != NULL; i += 6 )
259  {
260  if( !showTest( &serverTestInfo[ i ] ) )
261  {
262  printf( "\n" );
263  break;
264  }
265  }
266  }
267 
268 /* Look up the test number corresponding to a test name. Returns +ve for a
269  client test, -ve for a server test, 0 for no-match */
270 
271 static int lookupTestNo( const char *testName )
272  {
273  int i;
274 
275  for( i = 1; clientTestInfo[ i ].testName != NULL; i++ )
276  {
277  if( !strcmp( testName + 1, clientTestInfo[ i ].testName + 1 ) )
278  return( i );
279  }
280  for( i = 1; serverTestInfo[ i ].testName != NULL; i++ )
281  {
282  if( !strcmp( testName + 1, serverTestInfo[ i ].testName + 1 ) )
283  return( -i );
284  }
285 
286  return( 0 );
287  }
288 
289 /****************************************************************************
290 * *
291 * Suite B TLS Routines Test *
292 * *
293 ****************************************************************************/
294 
295 /* Find an alias for an existing test */
296 
297 static const SUITEB_TEST_INFO *findAliasTest( const SUITEB_TEST_INFO *testInfo,
298  const char *testName )
299  {
300  int i;
301 
302  for( i = 0; testInfo[ i ].testName != NULL; i++ )
303  {
304  if( !strcmp( testInfo[ i ].testName, testName ) )
305  return( &testInfo[ i ] );
306  }
307 
308  assert( 0 );
309  return( NULL );
310  }
311 
312 /* Establish a Suite B server session */
313 
314 static int suitebServer( const int testNo, const char *hostName,
315  const int port, const int flags,
316  const BOOLEAN isServerTest )
317  {
318  CRYPT_SESSION cryptSession;
319  CRYPT_CONTEXT privateKey;
320  const SUITEB_TEST_INFO *testInfoPtr = isServerTest ? \
321  &serverTestInfo[ testNo ] : &clientTestInfo[ testNo ];
322  const char *testName = testInfoPtr->testName;
323  const BOOLEAN isLoopbackTest = \
324  ( !strcmp( hostName, "localhost" ) && port == 0 ) ? TRUE : FALSE;
325  const BOOLEAN sendHTTP = \
326  ( flags & TESTFLAG_SENDHTTPREQ ) ? TRUE : FALSE;
327  char filenameBuffer[ FILENAME_BUFFER_SIZE ];
328 #ifdef UNICODE_STRINGS
329  wchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];
330 #endif /* UNICODE_STRINGS */
331  SPECIAL_HANDLING_TYPE handlingTypeAlt = SPECIAL_NONE;
332  void *fileNamePtr = filenameBuffer;
333  int status;
334 
335  /* Make sure that we've been given a valid test number to run */
336  if( isServerTest )
337  {
338  if( testNo < SUITEB_FIRST_SERVER || testNo > SUITEB_LAST_SERVER )
339  return( FALSE );
340  }
341  else
342  {
343  if( testNo < SUITEB_FIRST_CLIENT || testNo > SUITEB_LAST_CLIENT )
344  return( FALSE );
345  }
346 
347  /* If it's an alias for another test, select the base test */
348  if( testInfoPtr->aliasTestName != NULL )
349  {
350  handlingTypeAlt = testInfoPtr->handlingType;
351  testInfoPtr = findAliasTest( isServerTest ? \
352  &serverTestInfo[ 1 ] : &clientTestInfo[ 1 ],
353  testInfoPtr->aliasTestName );
354  if( testInfoPtr == NULL )
355  {
356  assert( 0 );
357  return( FALSE );
358  }
359  }
360 
361  /* Acquire the init mutex */
362  acquireMutex();
363  cryptSuiteBTestConfig( SUITEB_TEST_NONE ); /* Clear any custom config */
364 
365  printf( "SVR: Running Suite B server " );
366  if( flags & TESTFLAG_GENERIC )
367  printf( "as generic test server.\n" );
368  else
369  printf( "with test %s.\n", testInfoPtr->testName );
370 
371  /* Create the SSL/TLS session */
372  status = cryptCreateSession( &cryptSession, CRYPT_UNUSED,
374  if( status == CRYPT_ERROR_PARAM3 ) /* SSL/TLS session access not available */
375  return( CRYPT_ERROR_NOTAVAIL );
376  if( cryptStatusError( status ) )
377  {
378  printf( "cryptCreateSession() failed with error code %d, line %d.\n",
379  status, __LINE__ );
380  return( FALSE );
381  }
382  status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_VERSION, 3 );
383  if( cryptStatusOK( status ) && testInfoPtr->serverOptions != 0 )
384  {
385  status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SSL_OPTIONS,
386  testInfoPtr->serverOptions );
387  }
388  if( testInfoPtr->clientAuthKeySizeBits > 0 )
389  {
390  /* Tell the test code to expect a client certificate */
391  cryptSuiteBTestConfig( 1000 );
392  }
393  if( cryptStatusError( status ) )
394  {
395  printf( "cryptSetAttribute() failed with error code %d, line %d.\n",
396  status, __LINE__ );
397  return( FALSE );
398  }
399 
400  /* Set up the server information */
401  if( isLoopbackTest )
402  {
403  /* We're running the loopback test, set up a local connect */
404  if( !setLocalConnect( cryptSession, 443 ) )
405  return( FALSE );
406  }
407  else
408  {
409  status = cryptSetAttributeString( cryptSession,
411  hostName, strlen( hostName ) );
412  if( cryptStatusOK( status ) && port != 0 && port != 443 )
413  status = cryptSetAttribute( cryptSession,
415  if( cryptStatusError( status ) )
416  {
417  printf( "cryptSetAttribute()/cryptSetAttributeString() failed "
418  "with error code %d, line %d.\n", status, __LINE__ );
419  return( FALSE );
420  }
421  }
422 
423  /* Set any custom server configuration that may be required. We have to
424  do this before we set the server key since some of the tests involve
425  invalid server keys */
426  switch( testInfoPtr->handlingType )
427  {
428  case SPECIAL_SVR_INVALIDCURVE:
429  /* Server sends non-Suite B curve */
430  status = cryptSuiteBTestConfig( SUITEB_TEST_SVRINVALIDCURVE );
431  break;
432 
433  case SPECIAL_BOTH_SUPPCURVES:
434  /* Client must send both P256 and P384 in supported curves
435  extension */
436  status = cryptSuiteBTestConfig( SUITEB_TEST_BOTHCURVES );
437  break;
438 
439  case SPECIAL_BOTH_SIGALGO:
440  /* Client must send both SHA256 and SHA384 in signature algos
441  extension */
442  status = cryptSuiteBTestConfig( SUITEB_TEST_BOTHSIGALGOS );
443  break;
444  }
445  if( cryptStatusError( status ) )
446  {
447  printf( "Custom config set failed with error code %d, line %d.\n",
448  status, __LINE__ );
449  return( FALSE );
450  }
451 
452  /* Add the server key */
454  testInfoPtr->serverKeySizeBits );
455 #ifdef UNICODE_STRINGS
456  mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
457  fileNamePtr = wcBuffer;
458 #endif /* UNICODE_STRINGS */
459  status = getPrivateKey( &privateKey, fileNamePtr, USER_PRIVKEY_LABEL,
461  if( cryptStatusOK( status ) )
462  {
463  status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_PRIVATEKEY,
464  privateKey );
465  cryptDestroyContext( privateKey );
466  }
467  if( cryptStatusError( status ) )
468  {
469  printf( "SVR: cryptSetAttribute/AttributeString() failed with error "
470  "code %d, line %d.\n", status, __LINE__ );
471  return( FALSE );
472  }
473 
474  /* For the loopback test we also increase the connection timeout to a
475  higher-than-normal level, since this gives us more time for tracing
476  through the code when debugging */
478 
479  /* Tell the client that we're ready to go */
480  releaseMutex();
481 
482  /* Activate the server session */
483  status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
484  if( ( testInfoPtr->result && !cryptStatusOK( status ) ) || \
485  ( !testInfoPtr->result && !cryptStatusError( status ) ) )
486  {
487  if( testInfoPtr->result )
488  printf( "SVR: Test %s failed, should have succeeded.\n",
489  testName );
490  else
491  printf( "SVR: Test %s succeeded, should have failed.\n",
492  testName );
493  if( cryptStatusError( status ) )
494  {
495  printExtError( cryptSession, "SVR: Failure reason is:", status,
496  __LINE__ );
497  }
498  cryptDestroySession( cryptSession );
499 
500  return( FALSE );
501  }
502 
503  /* Perform any custom post-activation checking that may be required */
504  if( testInfoPtr->handlingType != 0 || handlingTypeAlt != 0 )
505  {
506  const SPECIAL_HANDLING_TYPE handlingType = \
507  ( handlingTypeAlt != 0 ) ? handlingTypeAlt : \
508  testInfoPtr->handlingType;
509  BYTE buffer[ 1024 ];
510  int length;
511 
512  switch( handlingType )
513  {
514  case SPECIAL_CLI_TLSALERT:
515  status = cryptGetAttributeString( cryptSession,
517  &length );
518  if( cryptStatusError( status ) || \
519  memcmp( buffer, "Received TLS alert", 18 ) )
520  {
521  printf( "SVR: Test %s should have returned a TLS alert "
522  "but didn't.\n", testName );
523  return( FALSE );
524  }
525  break;
526  }
527  }
528 
529  /* If we're being asked to send HTTP data, return a basic HTML page */
530  if( sendHTTP )
531  {
532  const char serverReply[] = \
533  "HTTP/1.0 200 OK\n"
534  "Date: Fri, 7 September 2010 20:02:07 GMT\n"
535  "Server: cryptlib Suite B test\n"
536  "Content-Type: text/html\n"
537  "Connection: Close\n"
538  "\n"
539  "<!DOCTYPE HTML SYSTEM \"html.dtd\">\n"
540  "<html>\n"
541  "<head>\n"
542  "<title>cryptlib Suite B test page</title>\n"
543  "<body>\n"
544  "Test message from the cryptlib Suite B server.<p>\n"
545  "</body>\n"
546  "</html>\n";
547  char buffer[ FILEBUFFER_SIZE ];
548  int bytesCopied;
549 
550  /* Print the text of the request from the client */
551  status = cryptPopData( cryptSession, buffer, FILEBUFFER_SIZE,
552  &bytesCopied );
553  if( cryptStatusError( status ) )
554  {
555  printExtError( cryptSession, "SVR: Attempt to read data from "
556  "client", status, __LINE__ );
557  cryptDestroySession( cryptSession );
558  return( FALSE );
559  }
560  buffer[ bytesCopied ] = '\0';
561  printf( "---- Client sent %d bytes ----\n", bytesCopied );
562  puts( buffer );
563  puts( "---- End of output ----" );
564 
565  /* Send a reply */
566  status = cryptPushData( cryptSession, serverReply,
567  sizeof( serverReply ) - 1, &bytesCopied );
568  if( cryptStatusOK( status ) )
569  status = cryptFlushData( cryptSession );
570  if( cryptStatusError( status ) || \
571  bytesCopied != sizeof( serverReply ) - 1 )
572  {
573  printExtError( cryptSession, "Attempt to send data to client",
574  status, __LINE__ );
575  cryptDestroySession( cryptSession );
576  return( FALSE );
577  }
578  }
579 
580  /* Clean up */
581  status = cryptDestroySession( cryptSession );
582  if( cryptStatusError( status ) )
583  {
584  printf( "cryptDestroySession() failed with error code %d, line %d.\n",
585  status, __LINE__ );
586  return( FALSE );
587  }
588  printf( "SVR: Suite B server test %s succeeded.\n", testName );
589 
590  return( TRUE );
591  }
592 
593 /* Establish a Suite B client session */
594 
595 static int suitebClient( const int testNo, const char *hostName,
596  const int port, const int flags,
597  const BOOLEAN isServerTest )
598  {
599  CRYPT_SESSION cryptSession;
600  const SUITEB_TEST_INFO *testInfoPtr = isServerTest ? \
601  &serverTestInfo[ testNo ] : &clientTestInfo[ testNo ];
602  const BOOLEAN isLoopbackTest = \
603  ( !strcmp( hostName, "localhost" ) && port == 0 ) ? TRUE : FALSE;
604  const BOOLEAN sendHTTP = \
605  ( flags & TESTFLAG_SENDHTTPREQ ) ? TRUE : FALSE;
606  const char *testName = testInfoPtr->testName;
607  SPECIAL_HANDLING_TYPE handlingTypeAlt = SPECIAL_NONE;
608  int status;
609 
610  /* Make sure that we've been given a valid test number to run */
611  if( isServerTest )
612  {
613  if( testNo < SUITEB_FIRST_SERVER || testNo > SUITEB_LAST_SERVER )
614  return( FALSE );
615  }
616  else
617  {
618  if( testNo < SUITEB_FIRST_CLIENT || testNo > SUITEB_LAST_CLIENT )
619  return( FALSE );
620  }
621 
622  /* If it's an alias for another test, select the base test */
623  if( testInfoPtr->aliasTestName != NULL )
624  {
625  handlingTypeAlt = testInfoPtr->handlingType;
626  testInfoPtr = findAliasTest( isServerTest ? \
627  &serverTestInfo[ 1 ] : &clientTestInfo[ 1 ],
628  testInfoPtr->aliasTestName );
629  if( testInfoPtr == NULL )
630  {
631  assert( 0 );
632  return( FALSE );
633  }
634  }
635 
636  /* Wait for the server to finish initialising */
637  if( waitMutex() == CRYPT_ERROR_TIMEOUT )
638  {
639  printf( "Timed out waiting for server to initialise, line %d.\n",
640  __LINE__ );
641  return( FALSE );
642  }
643  if( !isLoopbackTest )
644  {
645  /* Clear any custom config, provided we're not running a loopback
646  test, in which case we'd be overwriting the options that have
647  already been set by the server */
648  cryptSuiteBTestConfig( SUITEB_TEST_NONE );
649  }
650 
651  printf( "Running Suite B client " );
652  if( flags & TESTFLAG_GENERIC )
653  printf( "as generic test client.\n" );
654  else
655  printf( "with test %s.\n", testInfoPtr->testName );
656 
657  /* Create the SSL/TLS session */
658  status = cryptCreateSession( &cryptSession, CRYPT_UNUSED,
660  if( status == CRYPT_ERROR_PARAM3 ) /* SSL/TLS session access not available */
661  return( CRYPT_ERROR_NOTAVAIL );
662  if( cryptStatusError( status ) )
663  {
664  printf( "cryptCreateSession() failed with error code %d, line %d.\n",
665  status, __LINE__ );
666  return( FALSE );
667  }
668  status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_VERSION, 3 );
669  if( cryptStatusOK( status ) && testInfoPtr->clientOptions != 0 )
670  {
671  status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_SSL_OPTIONS,
672  testInfoPtr->clientOptions );
673  }
674  if( cryptStatusError( status ) )
675  {
676  printf( "cryptSetAttribute() failed with error code %d, line %d.\n",
677  status, __LINE__ );
678  return( FALSE );
679  }
680 
681  /* Set up the client information */
682  if( isLoopbackTest )
683  {
684  /* We're running the loopback test, set up a local connect */
685  if( !setLocalConnect( cryptSession, 443 ) )
686  return( FALSE );
687  }
688  else
689  {
690  status = cryptSetAttributeString( cryptSession,
692  hostName, strlen( hostName ) );
693  if( cryptStatusOK( status ) && port != 0 && port != 443 )
694  status = cryptSetAttribute( cryptSession,
696  if( cryptStatusError( status ) )
697  {
698  printf( "cryptSetAttribute()/cryptSetAttributeString() failed "
699  "with error code %d, line %d.\n", status, __LINE__ );
700  return( FALSE );
701  }
702  }
703  if( cryptStatusOK( status ) && \
704  testInfoPtr->clientAuthKeySizeBits > 0 )
705  {
706  CRYPT_CONTEXT privateKey;
707  char filenameBuffer[ FILENAME_BUFFER_SIZE ];
708 #ifdef UNICODE_STRINGS
709  wchar_t wcBuffer[ FILENAME_BUFFER_SIZE ];
710 #endif /* UNICODE_STRINGS */
711  void *fileNamePtr = filenameBuffer;
712 
713  /* Depending on which server we're testing against we need to use
714  different private keys */
716  testInfoPtr->clientAuthKeySizeBits );
717 #ifdef UNICODE_STRINGS
718  mbstowcs( wcBuffer, filenameBuffer, strlen( filenameBuffer ) + 1 );
719  fileNamePtr = wcBuffer;
720 #endif /* UNICODE_STRINGS */
721  status = getPrivateKey( &privateKey, fileNamePtr, USER_PRIVKEY_LABEL,
723  if( cryptStatusOK( status ) )
724  {
725  status = cryptSetAttribute( cryptSession,
726  CRYPT_SESSINFO_PRIVATEKEY, privateKey );
727  cryptDestroyContext( privateKey );
728  }
729  }
730  if( cryptStatusError( status ) )
731  {
732  printf( "cryptSetAttribute/AttributeString() failed with error code "
733  "%d, line %d.\n", status, __LINE__ );
734  return( FALSE );
735  }
736 
737  /* For the loopback test we also increase the connection timeout to a
738  higher-than-normal level, since this gives us more time for tracing
739  through the code when debugging */
741 
742  /* Set any custom client configuration that may be required */
743  switch( testInfoPtr->handlingType )
744  {
745  case SPECIAL_CLI_INVALIDCURVE:
746  /* Client sends non-Suite B curve */
747  status = cryptSuiteBTestConfig( SUITEB_TEST_CLIINVALIDCURVE );
748  break;
749 
750  case SPECIAL_BOTH_SUPPALGO:
751  /* Client must send supported_curves extension for both P256
752  and P384 curves */
753  status = cryptSuiteBTestConfig( SUITEB_TEST_BOTHSIGALGOS );
754  break;
755  }
756  if( cryptStatusError( status ) )
757  {
758  printf( "Custom config set failed with error code %d, line %d.\n",
759  status, __LINE__ );
760  return( FALSE );
761  }
762 
763  /* Activate the client session */
764  status = cryptSetAttribute( cryptSession, CRYPT_SESSINFO_ACTIVE, TRUE );
765  if( ( testInfoPtr->result && !cryptStatusOK( status ) ) || \
766  ( !testInfoPtr->result && !cryptStatusError( status ) ) )
767  {
768  if( testInfoPtr->result )
769  printf( "Test %s failed, should have succeeded.\n", testName );
770  else
771  printf( "Test %s succeeded, should have failed.\n", testName );
772  if( cryptStatusError( status ) )
773  {
774  printExtError( cryptSession, "Failure reason is:", status,
775  __LINE__ );
776  }
777  cryptDestroySession( cryptSession );
778 
779  return( FALSE );
780  }
781 
782  /* Perform any custom post-activation checking that may be required */
783  if( testInfoPtr->handlingType != 0 || handlingTypeAlt != 0 )
784  {
785  const SPECIAL_HANDLING_TYPE handlingType = \
786  ( handlingTypeAlt != 0 ) ? handlingTypeAlt : \
787  testInfoPtr->handlingType;
788  BYTE buffer[ 1024 ];
789  int length;
790 
791  switch( handlingType )
792  {
793  case SPECIAL_CLI_INVALIDCURVE:
794  case SPECIAL_BOTH_SUPPALGO:
795  /* Handled by checking whether the session activation
796  failed/succeeded */
797  break;
798 
799  case SPECIAL_SVR_TLSALERT:
800  status = cryptGetAttributeString( cryptSession,
802  &length );
803  if( cryptStatusError( status ) || \
804  memcmp( buffer, "Received TLS alert", 18 ) )
805  {
806  printf( "Test %s should have returned a TLS alert but "
807  "didn't.\n", testName );
808  return( FALSE );
809  }
810  break;
811 
812  case SPECIAL_SVR_INVALIDCURVE:
813  /* Handled/checked on the server */
814  break;
815 
816  default:
817  assert( 0 );
818  return( FALSE );
819  }
820  }
821 
822  /* If we're being asked to send HTTP data, send a basic GET */
823  if( sendHTTP )
824  {
825  const char *fetchString = "GET / HTTP/1.0\r\n\r\n";
826  const int fetchStringLen = sizeof( fetchString ) - 1;
827  int bytesCopied;
828 
829  status = cryptPushData( cryptSession, fetchString,
830  fetchStringLen, &bytesCopied );
831  if( cryptStatusOK( status ) )
832  status = cryptFlushData( cryptSession );
833  if( cryptStatusError( status ) || bytesCopied != fetchStringLen )
834  {
835  printExtError( cryptSession, "Attempt to send data to server",
836  status, __LINE__ );
837  cryptDestroySession( cryptSession );
838  return( FALSE );
839  }
840  }
841 
842  /* Clean up */
843  status = cryptDestroySession( cryptSession );
844  if( cryptStatusError( status ) )
845  {
846  printf( "cryptDestroySession() failed with error code %d, line %d.\n",
847  status, __LINE__ );
848  return( FALSE );
849  }
850  printf( "Suite B client test %s succeeded.\n", testName );
851 
852  return( TRUE );
853  }
854 
855 static int suitebTest( const BOOLEAN isServer, const int testNo,
856  const char *hostName, const int port,
857  const int flags )
858  {
859  BOOLEAN isServerTest = FALSE;
860  int value = testNo, status;
861 
862  if( value < 0 )
863  {
864  isServerTest = TRUE;
865  value = -value;
866  }
867 
868  /* Set up default argument values if required */
869  if( hostName == NULL )
870  hostName = "localhost";
871 
872  /* Run the test client or server */
873  createMutex();
874  if( isServer )
875  status = suitebServer( value, hostName, port, flags,
876  isServerTest );
877  else
878  status = suitebClient( value, hostName, port, flags,
879  isServerTest );
880  destroyMutex();
881  return( status );
882  }
883 
884 #ifdef WINDOWS_THREADS
885 
886 unsigned __stdcall suitebServerThread( void *arg )
887  {
888  BOOLEAN isServerTest = FALSE;
889  int value = *( ( int * ) arg );
890 
891  if( value < 0 )
892  {
893  isServerTest = TRUE;
894  value = -value;
895  }
896  suitebServer( value, "localhost", 0, FALSE, isServerTest );
897  _endthreadex( 0 );
898  return( 0 );
899  }
900 
902  {
903  HANDLE hThread;
904  unsigned threadID;
905  BOOLEAN isServerTest = FALSE;
906  int value = -1, status; /* +ve = client, -ve = server */
907 
908  /* Start the server */
909  createMutex();
910  hThread = ( HANDLE ) _beginthreadex( NULL, 0, suitebServerThread,
911  &value, 0, &threadID );
912  Sleep( 1000 );
913 
914  /* Connect to the local server */
915  if( value < 0 )
916  {
917  isServerTest = TRUE;
918  value = -value;
919  }
920  status = suitebClient( value, "localhost", 0, FALSE, isServerTest );
921  waitForThread( hThread );
922  destroyMutex();
923  return( status );
924  }
925 #endif /* WINDOWS_THREADS */
926 
927 /****************************************************************************
928 * *
929 * Suite B Keygen *
930 * *
931 ****************************************************************************/
932 
933 /* Generate an ECDSA private key and certificate request */
934 
935 static const CERT_DATA FAR_BSS certRequestData[] = {
936  /* Identification information */
937  { CRYPT_CERTINFO_COUNTRYNAME, IS_STRING, 0, TEXT( "NZ" ) },
938  { CRYPT_CERTINFO_ORGANIZATIONNAME, IS_STRING, 0, TEXT( "Dave's Wetaburgers" ) },
939  { CRYPT_CERTINFO_COMMONNAME, IS_STRING, 0, TEXT( "localhost" ) },
940 
941  { CRYPT_ATTRIBUTE_NONE, 0, 0, NULL }
942  };
943 
944 static int generateKey( const int keyBits, const char *certRequestFileName )
945  {
946  CRYPT_KEYSET cryptKeyset;
947  CRYPT_CERTIFICATE cryptCertRequest;
949  FILE *filePtr;
951  char filenameBuffer[ FILENAME_BUFFER_SIZE ];
952  void *fileNamePtr = filenameBuffer;
953  int length, count, status;
954 
955  /* Generate a key to certify. We can't just reuse the built-in test key
956  because this has already been used as the CA key and the keyset code
957  won't allow it to be added to a keyset as both a CA key and user key,
958  so we have to generate a new one */
959  status = cryptCreateContext( &cryptKey, CRYPT_UNUSED, CRYPT_ALGO_ECDSA );
960  if( cryptStatusOK( status ) )
961  status = cryptSetAttribute( cryptKey, CRYPT_CTXINFO_KEYSIZE,
962  keyBits >> 3 );
963  if( cryptStatusOK( status ) )
964  {
965  status = cryptSetAttributeString( cryptKey, CRYPT_CTXINFO_LABEL,
968  }
969  if( cryptStatusOK( status ) )
970  status = cryptGenerateKey( cryptKey );
971  if( cryptStatusError( status ) )
972  {
973  printf( "Key generation failed with error code %d, line %d.\n",
974  status, __LINE__ );
975  return( FALSE );
976  }
977 
978  /* Create the certificate request for the new key */
979  status = cryptCreateCert( &cryptCertRequest, CRYPT_UNUSED,
981  if( cryptStatusOK( status ) )
982  status = cryptSetAttribute( cryptCertRequest,
984  if( cryptStatusOK( status ) && \
985  !addCertFields( cryptCertRequest, certRequestData, __LINE__ ) )
986  return( FALSE );
987  if( cryptStatusOK( status ) )
988  status = cryptSignCert( cryptCertRequest, cryptKey );
989  if( cryptStatusOK( status ) )
990  {
991  status = cryptExportCert( certBuffer, BUFFER_SIZE, &length,
993  cryptCertRequest );
994  cryptDestroyCert( cryptCertRequest );
995  }
996  if( cryptStatusError( status ) )
997  {
998  printf( "Certificate request creation failed with error code %d, "
999  "line %d.\n", status, __LINE__ );
1000  return( FALSE );
1001  }
1002  if( ( filePtr = fopen( certRequestFileName, "wb" ) ) != NULL )
1003  {
1004  count = fwrite( certBuffer, 1, length, filePtr );
1005  fclose( filePtr );
1006  }
1007  if( filePtr == NULL || count < length )
1008  {
1009  printf( "Couldn't write certificate request to disk, line %d.\n",
1010  __LINE__ );
1011  return( FALSE );
1012  }
1013 
1014  /* Create the keyset and add the private key to it */
1016  keyBits );
1017  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
1018  fileNamePtr, CRYPT_KEYOPT_CREATE );
1019  if( cryptStatusError( status ) )
1020  {
1021  printf( "cryptKeysetOpen() failed with error code %d, line %d.\n",
1022  status, __LINE__ );
1023  return( FALSE );
1024  }
1025  status = cryptAddPrivateKey( cryptKeyset, cryptKey,
1027  if( cryptStatusError( status ) )
1028  {
1029  printExtError( cryptKeyset, "cryptAddPrivateKey()", status,
1030  __LINE__ );
1031  return( FALSE );
1032  }
1033  cryptDestroyContext( cryptKey );
1034  cryptKeysetClose( cryptKeyset );
1035 
1036  return( TRUE );
1037  }
1038 
1039 /* Add an ECDSA certificate to a previously-generated key */
1040 
1041 static int updateKey( const int keyBits, const char *certFileName )
1042  {
1043  CRYPT_KEYSET cryptKeyset;
1044  CRYPT_CERTIFICATE cryptCert;
1045  char filenameBuffer[ FILENAME_BUFFER_SIZE ];
1046  void *fileNamePtr = filenameBuffer;
1047  int status;
1048 
1049  /* Import the certificate from the file */
1050  status = importCertFile( &cryptCert, certFileName );
1051  if( cryptStatusError( status ) )
1052  {
1053  printf( "Couldn't import certificate from file, status %d, "
1054  "line %d.\n", status, __LINE__ );
1055  return( FALSE );
1056  }
1057 
1058  /* Add the certificate to the file */
1060  keyBits );
1061  status = cryptKeysetOpen( &cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE,
1062  fileNamePtr, CRYPT_KEYOPT_NONE );
1063  if( cryptStatusOK( status ) )
1064  {
1065  status = cryptAddPublicKey( cryptKeyset, cryptCert );
1066  cryptKeysetClose( cryptKeyset );
1067  }
1068  if( cryptStatusError( status ) )
1069  {
1070  printf( "Couldn't update private key with certificate, status %d, "
1071  "line %d.\n", status, __LINE__ );
1072  return( FALSE );
1073  }
1074 
1075  return( TRUE );
1076  }
1077 
1078 /****************************************************************************
1079 * *
1080 * Suite B Test Application *
1081 * *
1082 ****************************************************************************/
1083 
1084 /* Show usage and exit */
1085 
1086 static void usageExit( void )
1087  {
1088  puts( "Usage: testlib c|s [-h hostname] [-p port] [-s] <test>" );
1089 
1090  puts( " Operation type:" );
1091  puts( " c = Run test as the client." );
1092  puts( " s = Run test as the server." );
1093  puts( " <test> = Test name, e.g. 'A.1.1.1', or '128'/'256' to run as a" );
1094  puts( " generic 128/256-bit client or server." );
1095  puts( "" );
1096 
1097  puts( " Options:" );
1098  puts( " -s = Send HTTP request." );
1099  puts( " -h <hostname> = Host name (default localhost)." );
1100  puts( " -p <port> = Port (default 443 or 4443)." );
1101  puts( " -- = End of arg list." );
1102  puts( "" );
1103  showTestInfo();
1104  puts( "" );
1105 
1106  puts( " Keygen commands:" );
1107  puts( "" );
1108  puts( " kg [256|384] <cert-request filename>" );
1109  puts( " = Generate 256/384-bit key and PKCS #10 cert request." );
1110  puts( " ka [256|384] <certificate filename>" );
1111  puts( " = Add issued certificate to previously-generated 256/384-bit key." );
1112  puts( "" );
1113 
1114  exit( EXIT_FAILURE );
1115  }
1116 
1117 /* Process command-line arguments */
1118 
1119 static int processArgs( int argc, char **argv, int *testNo,
1120  const char **stringArg, int *intArg,
1121  BOOLEAN *isServer, BOOLEAN *sendHTTPheader )
1122  {
1123  const char *argPtr = argv[ 0 ];
1124  BOOLEAN moreArgs = TRUE;
1125  int value;
1126 
1127  /* Clear return values */
1128  *testNo = *intArg = 0;
1129  *stringArg = NULL;
1130  *isServer = *sendHTTPheader = FALSE;
1131 
1132  /* No args means display a usage message */
1133  if( argc <= 0 )
1134  usageExit();
1135 
1136  /* Process the main command */
1137  switch( tolower( *argPtr ) )
1138  {
1139  case 'c':
1140  *isServer = FALSE;
1141  argv++; argc--;
1142  break;
1143 
1144  case 's':
1145  *isServer = TRUE;
1146  argv++; argc--;
1147  break;
1148 
1149  case 'k':
1150  switch( tolower( argPtr[ 1 ] ) )
1151  {
1152  case 'g':
1153  *testNo = -1; /* Generate key */
1154  break;
1155 
1156  case 'a':
1157  *testNo = -2; /* Add certificate */
1158  break;
1159 
1160  default:
1161  printf( "Error: Unknown key management option '%c'.\n",
1162  argPtr[ 1 ] );
1163  return( FALSE );
1164  }
1165 
1166  /* Get the key size */
1167  argv++; argc--;
1168  if( argc <= 0 )
1169  {
1170  puts( "Error: Missing key size." );
1171  return( FALSE );
1172  }
1173  argPtr = argv[ 0 ];
1174  value = -1;
1175  if( *argPtr == '2' || *argPtr == '3' )
1176  value = atoi( argv[ 0 ] );
1177  if( value != 256 && value != 384 )
1178  {
1179  puts( "Error: Key size must be '256' or '384'." );
1180  return( FALSE );
1181  }
1182  *intArg = value;
1183 
1184  /* Get the filename */
1185  argv++; argc--;
1186  if( argc <= 0 )
1187  {
1188  puts( "Error: Missing file name." );
1189  return( FALSE );
1190  }
1191  *stringArg = argv[ 0 ];
1192  if( *testNo == -2 )
1193  {
1194  FILE *filePtr;
1195 
1196  /* Make sure that the specified input file exists */
1197  filePtr = fopen( argv[ 0 ], "rb" );
1198  if( filePtr == NULL )
1199  {
1200  printf( "Error: Can't open '%s'.\n", argv[ 0 ] );
1201  return( FALSE );
1202  }
1203  fclose( filePtr );
1204  }
1205 
1206  /* Make sure that's all */
1207  argv++; argc--;
1208  if( argc != 0 )
1209  {
1210  printf( "Error: Spurious option '%s'.\n", argv[ 0 ] );
1211  return( FALSE );
1212  }
1213  break;
1214 
1215  default:
1216  usageExit();
1217  }
1218 
1219  /* Process any additional arguments */
1220  while( argc > 0 && moreArgs )
1221  {
1222  argPtr = argv[ 0 ];
1223  if( *argPtr == '1' || *argPtr == '2' )
1224  {
1225  /* The user has asked to run as a generic 128/256-bit client or
1226  server, map it to an equivalent test number */
1227  value = atoi( argPtr );
1228  if( value != 128 && value != 256 )
1229  {
1230  puts( "Error: Generic client/server type must be '128' "
1231  "or '256'." );
1232  return( FALSE );
1233  }
1234  if( value == 128 )
1235  argPtr = "A.1.1.1";
1236  else
1237  argPtr = "A.1.2.1";
1238  }
1239  if( *argPtr == 'a' || *argPtr == 'A' )
1240  {
1241  int value;
1242 
1243  if( *testNo != 0 )
1244  usageExit();
1245 
1246  /* Perform a basic validity test that the argument is in the
1247  format "A.[12].[1-3]" */
1248  if( argPtr[ 1 ] != '.' || \
1249  ( argPtr[ 2 ] != '1' && argPtr[ 2 ] != '2' ) || \
1250  argPtr[ 3 ] != '.' || \
1251  ( argPtr[ 4 ] < '1' || argPtr[ 4 ] > '3' ) )
1252  usageExit();
1253  value = lookupTestNo( argPtr );
1254  if( value == 0 )
1255  {
1256  printf( "Error: Unknown test type '%s'.\n", argPtr );
1257  return( FALSE );
1258  }
1259  *testNo = value;
1260  argv++;
1261  argc--;
1262  continue;
1263  }
1264  if( *argPtr != '-' )
1265  {
1266  printf( "Error: Unknown argument '%s'.\n", argPtr );
1267  return( FALSE );
1268  }
1269  argPtr++;
1270  while( *argPtr )
1271  {
1272  switch( toupper( *argPtr ) )
1273  {
1274  case '-':
1275  moreArgs = FALSE; /* GNU-style end-of-args flag */
1276  break;
1277 
1278  case 'H':
1279  if( *stringArg != NULL )
1280  usageExit();
1281  argv++; argc--;
1282  if( argc <= 0 )
1283  {
1284  puts( "Error: Missing host name" );
1285  return( FALSE );
1286  }
1287  *stringArg = argv[ 0 ];
1288  argPtr = "";
1289  break;
1290 
1291  case 'P':
1292  if( *intArg != 0 )
1293  usageExit();
1294  argv++; argc--;
1295  if( argc <= 0 )
1296  {
1297  puts( "Error: Missing port number" );
1298  return( FALSE );
1299  }
1300  value = atoi( argv[ 0 ] );
1301  if( value < 20 || value > 64000 )
1302  usageExit();
1303  *intArg = value;
1304  argPtr = "";
1305  break;
1306 
1307  case 'S':
1308  if( *sendHTTPheader != FALSE )
1309  usageExit();
1310  *sendHTTPheader = TRUE;
1311  argPtr++;
1312  break;
1313 
1314  default:
1315  printf( "Error: Unknown argument '%c'.\n", *argPtr );
1316  return( FALSE );
1317  }
1318  }
1319  argv++;
1320  argc--;
1321  }
1322  if( *testNo == 0 )
1323  {
1324  puts( "Error: Missing test name" );
1325  return( FALSE );
1326  }
1327 
1328  return( TRUE );
1329  }
1330 
1331 /* The main entry point for the Suite B test application */
1332 
1333 int suiteBMain( int argc, char **argv )
1334  {
1335  const char *stringArg;
1336  BOOLEAN isServer, sendHTTPheader;
1337  int testNo, intArg, status;
1338  void testSystemSpecific1( void );
1339  void testSystemSpecific2( void );
1340 
1341  printf( "testlib - cryptlib %d-bit Suite B test framework.\n",
1342  ( int ) sizeof( long ) * 8 ); /* Cast for gcc */
1343  puts( "Copyright Peter Gutmann 1995 - 2011." );
1344  puts( "" );
1345 
1346  /* Skip the program name and process any command-line arguments */
1347  argv++; argc--;
1348  status = processArgs( argc, argv, &testNo, &stringArg, &intArg,
1349  &isServer, &sendHTTPheader );
1350  if( !status )
1351  exit( EXIT_FAILURE );
1352 
1353  /* Make sure that various system-specific features are set right */
1355 
1356  /* Initialise cryptlib */
1357  status = cryptInit();
1358  if( cryptStatusError( status ) )
1359  {
1360  printf( "\ncryptInit() failed with error code %d, line %d.\n",
1361  status, __LINE__ );
1362  exit( EXIT_FAILURE );
1363  }
1364 
1365  /* In order to avoid having to do a randomness poll for every test run,
1366  we bypass the randomness-handling by adding some junk. This is only
1367  enabled when cryptlib is built in debug mode so it won't work with
1368  any production systems */
1369  cryptAddRandom( "xyzzy", 5 );
1370 
1371  /* Perform a general sanity check to make sure that the self-test is
1372  being run the right way */
1373  if( !checkFileAccess() )
1374  exit( EXIT_FAILURE );
1375 
1376  /* Make sure that further system-specific features that require cryptlib
1377  to be initialised to check are set right */
1379 
1380  /* If the test number is negative, it's a special-case non-test
1381  operation */
1382  if( testNo < 0 )
1383  {
1384  switch( testNo )
1385  {
1386  case -1:
1387  status = generateKey( intArg, stringArg );
1388  if( status == TRUE )
1389  printf( "Wrote %d-bit certificate request to "
1390  "file '%s'.\n\n", intArg, stringArg );
1391  break;
1392 
1393  case -2:
1394  status = updateKey( intArg, stringArg );
1395  if( status == TRUE )
1396  printf( "Updated %d-bit key with certificate from "
1397  "file '%s'.\n\n", intArg, stringArg );
1398  break;
1399  }
1400  }
1401  else
1402  {
1403  /* Run the selected test */
1404  status = suitebTest( isServer, testNo, stringArg, intArg,
1405  sendHTTPheader );
1406  }
1407 
1408  /* Clean up and exit */
1409  cryptEnd();
1410  return( ( status == TRUE ) ? EXIT_SUCCESS : EXIT_FAILURE );
1411  }
1412 #endif /* CONFIG_SUITEB_TESTS */