1 /****************************************************************************
2 * *
3 * cryptlib Internal String API *
4 * Copyright Peter Gutmann 1992-2014 *
5 * *
6 ****************************************************************************/
7
8 #if defined( INC_ALL )
9 #include "crypt.h"
10 #else
11 #include "crypt.h"
12 #endif /* Compiler-specific includes */
13
14 /****************************************************************************
15 * *
16 * General-purpose String Functions *
17 * *
18 ****************************************************************************/
19
20 /* Perform various string-processing operations */
21
22 CHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1 ) ) \
strFindCh(IN_BUFFER (strLen)const char * str,IN_LENGTH_SHORT const int strLen,IN_CHAR const int findCh)23 int strFindCh( IN_BUFFER( strLen ) const char *str,
24 IN_LENGTH_SHORT const int strLen,
25 IN_CHAR const int findCh )
26 {
27 int i;
28
29 assert( isReadPtr( str, strLen ) );
30
31 REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
32 REQUIRES( findCh >= 0 && findCh <= 0x7F );
33
34 for( i = 0; i < strLen; i++ )
35 {
36 if( str[ i ] == findCh )
37 return( i );
38 }
39
40 return( -1 );
41 }
42
43 CHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1, 3 ) ) \
strFindStr(IN_BUFFER (strLen)const char * str,IN_LENGTH_SHORT const int strLen,IN_BUFFER (findStrLen)const char * findStr,IN_LENGTH_SHORT const int findStrLen)44 int strFindStr( IN_BUFFER( strLen ) const char *str,
45 IN_LENGTH_SHORT const int strLen,
46 IN_BUFFER( findStrLen ) const char *findStr,
47 IN_LENGTH_SHORT const int findStrLen )
48 {
49 const int findCh = toUpper( findStr[ 0 ] );
50 int i;
51
52 assert( isReadPtr( str, strLen ) );
53 assert( isReadPtr( findStr, findStrLen ) );
54
55 REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
56 REQUIRES( findStrLen > 0 && findStrLen < MAX_INTLENGTH_SHORT );
57 REQUIRES( findCh >= 0 && findCh <= 0x7F );
58
59 for( i = 0; i <= strLen - findStrLen; i++ )
60 {
61 if( toUpper( str[ i ] ) == findCh && \
62 !strCompare( str + i, findStr, findStrLen ) )
63 return( i );
64 }
65
66 return( -1 );
67 }
68
69 CHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1 ) ) \
strSkipWhitespace(IN_BUFFER (strLen)const char * str,IN_LENGTH_SHORT const int strLen)70 int strSkipWhitespace( IN_BUFFER( strLen ) const char *str,
71 IN_LENGTH_SHORT const int strLen )
72 {
73 int i;
74
75 assert( isReadPtr( str, strLen ) );
76
77 REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
78
79 for( i = 0; i < strLen && ( str[ i ] == ' ' || str[ i ] == '\t' ); i++ );
80 return( ( i < strLen ) ? i : -1 );
81 }
82
83 CHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1 ) ) \
strSkipNonWhitespace(IN_BUFFER (strLen)const char * str,IN_LENGTH_SHORT const int strLen)84 int strSkipNonWhitespace( IN_BUFFER( strLen ) const char *str,
85 IN_LENGTH_SHORT const int strLen )
86 {
87 int i;
88
89 assert( isReadPtr( str, strLen ) );
90
91 REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
92
93 /* This differs slightly from strSkipWhitespace() in that EOL is also
94 counted as whitespace so there's never an error condition unless
95 we don't find anything at all */
96 for( i = 0; i < strLen && str[ i ] != ' ' && str[ i ] != '\t'; i++ );
97 return( i > 0 ? i : -1 );
98 }
99
100 CHECK_RETVAL_STRINGOP STDC_NONNULL_ARG( ( 1, 2 ) ) \
strStripWhitespace(OUT_PTR_COND const char ** newStringPtr,IN_BUFFER (strLen)const char * string,IN_LENGTH_SHORT const int strLen)101 int strStripWhitespace( OUT_PTR_COND const char **newStringPtr,
102 IN_BUFFER( strLen ) const char *string,
103 IN_LENGTH_SHORT const int strLen )
104 {
105 int startPos, endPos;
106
107 assert( isReadPtr( newStringPtr, sizeof( char * ) ) );
108 assert( isReadPtr( string, strLen ) );
109
110 REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
111
112 /* Clear return value */
113 *newStringPtr = NULL;
114
115 /* Skip leading and trailing whitespace */
116 for( startPos = 0;
117 startPos < strLen && \
118 ( string[ startPos ] == ' ' || string[ startPos ] == '\t' );
119 startPos++ );
120 if( startPos >= strLen )
121 return( -1 );
122 *newStringPtr = string + startPos;
123 for( endPos = strLen;
124 endPos > startPos && \
125 ( string[ endPos - 1 ] == ' ' || string[ endPos - 1 ] == '\t' );
126 endPos-- );
127 ENSURES( endPos - startPos > 0 );
128 return( endPos - startPos );
129 }
130
131 /****************************************************************************
132 * *
133 * Special-purpose String Functions *
134 * *
135 ****************************************************************************/
136
137 /* Extract a substring from a string. This converts:
138
139 string startOffset strLen
140 | | |
141 v v v
142 +-------------------+---------------+-------------------+
143 | Processed data | Whitespace | Remaining data |
144 +-------------------+---------------+-------------------+
145
146 into:
147
148 newStr length
149 | |
150 v v
151 +-------------------+
152 | Remaining data |
153 +-------------------+
154
155 The order of the parameters is a bit unusual, normally we'd use
156 { str, strLen } but this makes things a bit confusing for the caller, for
157 whom it's more logical to group the parameters based on the overall
158 operation being performed, which to extract a substring beginning at
159 startOffset is { str, startOffset, strLen } */
160
161 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 2 ) ) \
strExtract(OUT_PTR_COND const char ** newStringPtr,IN_BUFFER (strLen)const char * string,IN_LENGTH_SHORT_Z const int startOffset,IN_LENGTH_SHORT const int strLen)162 int strExtract( OUT_PTR_COND const char **newStringPtr,
163 IN_BUFFER( strLen ) const char *string,
164 IN_LENGTH_SHORT_Z const int startOffset,
165 IN_LENGTH_SHORT const int strLen )
166 {
167 const int newLen = strLen - startOffset;
168
169 assert( isReadPtr( newStringPtr, sizeof( char * ) ) );
170 assert( isReadPtr( string, strLen ) );
171
172 REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
173 REQUIRES( startOffset >= 0 && startOffset <= strLen && \
174 startOffset < MAX_INTLENGTH_SHORT );
175 /* May be zero if we're extracting from the start of the
176 string; may be equal to strLen if it's the entire
177 remaining string */
178
179 /* Clear return value */
180 *newStringPtr = NULL;
181
182 if( newLen < 1 || newLen > strLen || newLen >= MAX_INTLENGTH_SHORT )
183 return( -1 );
184 return( strStripWhitespace( newStringPtr, string + startOffset, newLen ) );
185 }
186
187 /* Parse a numeric or hex string into an integer value. Safe conversion of a
188 numeric string gets a bit problematic because atoi() can't really
189 indicate an error except by returning 0, which is indistinguishable from
190 a zero numeric value. To handle this we have to perform the conversion
191 ourselves */
192
193 CHECK_RETVAL STDC_NONNULL_ARG( ( 1, 3 ) ) \
IN_BUFFER(strLen)194 int strGetNumeric( IN_BUFFER( strLen ) const char *str,
195 IN_LENGTH_SHORT const int strLen,
196 OUT_INT_Z int *numericValue,
197 IN_RANGE( 0, 100 ) const int minValue,
198 IN_RANGE( minValue, MAX_INTLENGTH ) const int maxValue )
199 {
200 int i, value;
201
202 assert( isReadPtr( str, strLen ) );
203 assert( isWritePtr( numericValue, sizeof( int ) ) );
204
205 REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
206 REQUIRES( minValue >= 0 && minValue < maxValue && \
207 maxValue <= MAX_INTLENGTH );
208
209 /* Clear return value */
210 *numericValue = 0;
211
212 /* Make sure that the value is within the range 'n' ... 'nnnnnnn' */
213 if( strLen < 1 || strLen > 7 )
214 return( CRYPT_ERROR_BADDATA );
215
216 /* Process the numeric string. Note that the redundant 'value < 0'
217 check is necessary in order to prevent gcc from detecting what it
218 thinks is Undefined Behaviour (UB) and removing further checks from
219 the code. In addition the second check for MAX_INTLENGTH - ch isn't
220 really necessary because we know that value < MAX_INTLENGTH / 10,
221 which means that value <= MAX_INTLENGTH / 10 - 1, so
222 value * 10 <= MAX_INTLENGTH - 10, therefore
223 value * 10 < MAX_INTLENGTH - 9, so value * 10 < MAX_INTLENGTH - ch,
224 however we leave it in to make the condition explicit */
225 for( value = 0, i = 0; i < strLen; i++ )
226 {
227 const int ch = byteToInt( str[ i ] ) - '0';
228
229 if( ch < 0 || ch > 9 )
230 return( CRYPT_ERROR_BADDATA );
231 if( value < 0 || value >= MAX_INTLENGTH / 10 )
232 return( CRYPT_ERROR_BADDATA );
233 value *= 10;
234 if( value >= MAX_INTLENGTH - ch )
235 return( CRYPT_ERROR_BADDATA );
236 value += ch;
237 ENSURES( value >= 0 && value < MAX_INTLENGTH );
238 }
239
240 /* Make sure that the final value is within the specified range */
241 if( value < minValue || value > maxValue )
242 return( CRYPT_ERROR_BADDATA );
243
244 *numericValue = value;
245 return( CRYPT_OK );
246 }
247
248 CHECK_RETVAL STDC_NONNULL_ARG( ( 1 ) ) \
IN_BUFFER(strLen)249 int strGetHex( IN_BUFFER( strLen ) const char *str,
250 IN_LENGTH_SHORT const int strLen,
251 OUT_INT_Z int *numericValue,
252 IN_RANGE( 0, 100 ) const int minValue,
253 IN_RANGE( minValue, MAX_INTLENGTH ) const int maxValue )
254 {
255 #ifdef SYSTEM_16BIT
256 const int strMaxLen = ( maxValue > 0xFFF ) ? 4 : \
257 ( maxValue > 0xFF ) ? 3 : \
258 ( maxValue > 0xF ) ? 2 : 1;
259 #else
260 const int strMaxLen = ( maxValue > 0xFFFF ) ? 5 : \
261 ( maxValue > 0xFFF ) ? 4 : \
262 ( maxValue > 0xFF ) ? 3 : \
263 ( maxValue > 0xF ) ? 2 : 1;
264 #endif /* SYSTEM_16BIT */
265 int i, value = 0;
266
267 assert( isReadPtr( str, strLen ) );
268 assert( isWritePtr( numericValue, sizeof( int ) ) );
269
270 REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
271 REQUIRES( minValue >= 0 && minValue < maxValue && \
272 maxValue <= MAX_INTLENGTH );
273
274 /* Clear return value */
275 *numericValue = 0;
276
277 /* Make sure that the length is sensible for the value that we're
278 reading */
279 if( strLen < 1 || strLen > strMaxLen )
280 return( CRYPT_ERROR_BADDATA );
281
282 /* Process the numeric string. We don't have to perform the same level
283 of overflow checking as we do in strGetNumeric() because the maximum
284 value is capped to fit into an int */
285 for( i = 0; i < strLen; i++ )
286 {
287 const int ch = toLower( str[ i ] );
288
289 if( !isXDigit( ch ) )
290 return( CRYPT_ERROR_BADDATA );
291 value = ( value << 4 ) | \
292 ( ( ch <= '9' ) ? ch - '0' : ch - ( 'a' - 10 ) );
293 }
294 if( value < minValue || value > maxValue )
295 return( CRYPT_ERROR_BADDATA );
296
297 *numericValue = value;
298
299 return( CRYPT_OK );
300 }
301
302 /* Determine whether a string is printable or not, used when checking whether
303 it should be displayed to the caller as a text string or a hex dump */
304
305 CHECK_RETVAL_BOOL STDC_NONNULL_ARG( ( 1 ) ) \
strIsPrintable(IN_BUFFER (strLen)const void * str,IN_LENGTH_SHORT const int strLen)306 BOOLEAN strIsPrintable( IN_BUFFER( strLen ) const void *str,
307 IN_LENGTH_SHORT const int strLen )
308 {
309 const BYTE *strPtr = str;
310 int i;
311
312 assert( isReadPtr( str, strLen ) );
313
314 REQUIRES( strLen > 0 && strLen < MAX_INTLENGTH_SHORT );
315
316 for( i = 0; i < strLen; i++ )
317 {
318 const int ch = byteToInt( strPtr[ i ] );
319
320 if( !isValidTextChar( ch ) )
321 return( FALSE );
322 }
323
324 return( TRUE );
325 }
326
327 /* Sanitise a string before passing it back to the user. This is used to
328 clear potential problem characters (for example control characters)
329 from strings passed back from untrusted sources (nec verbum verbo
330 curabis reddere fidus interpres - Horace).
331
332 This function assumes that the string is in ASCII form rather than some
333 exotic character set, since this is used for processing text error
334 messages sent to us by remote systems we can reasonably assume that
335 they should be be, well, text error messages so that we're within our
336 rights to filter out non-text data.
337
338 The function returns a pointer to the string to allow it to be used in
339 the form printf( "..%s..", sanitiseString( string, strLen ) ). In
340 addition it formats the data to fit a fixed-length buffer, if the string
341 is longer than the indicated buffer size then it appends a '[...]' at the
342 end of the buffer to indicate that further data was truncated. The
343 transformation applied is as follows:
344
345 buffer strMaxLen
346 | |
347 v v
348 +---------------------------+ . .
349 | | ==> . .
350 +---------------------------+ . .
351 . . . .
352 |---------------| . |---------------|\0| .
353 . ^ . . .
354 |--------------------------------| |-----------------------|[...]\0|
355 | ^
356 +---- strLen ----+
357
358 so "Error string of arbitrary length..." with a buffer size of 20 would
359 become "Error string [...]" */
360
361 STDC_NONNULL_ARG( ( 1 ) ) \
sanitiseString(INOUT_BUFFER (strMaxLen,strLen)void * string,IN_LENGTH_SHORT const int strMaxLen,IN_LENGTH_SHORT const int strLen)362 char *sanitiseString( INOUT_BUFFER( strMaxLen, strLen ) void *string,
363 IN_LENGTH_SHORT const int strMaxLen,
364 IN_LENGTH_SHORT const int strLen )
365 {
366 BYTE *strPtr = string; /* See comment below */
367 const int strDataLen = min( strLen, strMaxLen );
368 int i;
369
370 assert( isWritePtr( string, strMaxLen ) );
371
372 REQUIRES_EXT( ( strLen > 0 && strLen < MAX_INTLENGTH_SHORT ), \
373 "(Internal error)" );
374 REQUIRES_EXT( ( strMaxLen > 0 && strMaxLen < MAX_INTLENGTH_SHORT ), \
375 "(Internal error)" );
376
377 /* Remove any potentially unsafe characters from the string, effectively
378 converting it from a 'BYTE *' to a 'char *'. This is also the reason
379 why the function prototype declares it as a 'void *', if it's declared
380 as a 'BYTE *' then the conversion process gives compilers and static
381 analysers headaches */
382 for( i = 0; i < strDataLen; i++ )
383 {
384 const int ch = byteToInt( strPtr[ i ] );
385
386 if( !isValidTextChar( ch ) )
387 strPtr[ i ] = '.';
388 }
389
390 /* If there was more input than we could fit into the buffer and
391 there's room for a continuation indicator, add this to the output
392 string */
393 if( ( strLen >= strMaxLen ) && ( strMaxLen > 8 ) )
394 memcpy( strPtr + strMaxLen - 6, "[...]", 5 ); /* Extra -1 for '\0' */
395
396 /* Terminate the string to allow it to be used in printf()-style
397 functions */
398 if( strLen < strMaxLen )
399 strPtr[ strLen ] = '\0';
400 else
401 strPtr[ strMaxLen - 1 ] = '\0';
402
403 /* We've converted the string from BYTE * to char * so it can be
404 returned as a standard text string */
405 return( ( char * ) strPtr );
406 }
407
408 /****************************************************************************
409 * *
410 * TR 24731 Safe stdlib Extensions *
411 * *
412 ****************************************************************************/
413
414 #ifndef __STDC_LIB_EXT1__
415
416 /* Minimal wrappers for the TR 24731 functions to map them to older stdlib
417 equivalents. Because of potential issues when comparing a (signed)
418 literal value -1 to the unsigned size_t we explicitly check for both
419 '( size_t ) -1' as well as a general check for a negative return value */
420
421 RETVAL_RANGE( -1, 0 ) \
mbstowcs_s(OUT size_t * retval,OUT_BUFFER_FIXED (dstmax)wchar_t * dst,IN_LENGTH_SHORT size_t dstmax,IN_BUFFER (len)const char * src,IN_LENGTH_SHORT size_t len)422 int mbstowcs_s( OUT size_t *retval,
423 OUT_BUFFER_FIXED( dstmax ) wchar_t *dst,
424 IN_LENGTH_SHORT size_t dstmax,
425 IN_BUFFER( len ) const char *src,
426 IN_LENGTH_SHORT size_t len )
427 {
428 size_t bytesCopied;
429
430 assert( isWritePtr( retval, sizeof( size_t ) ) );
431 assert( isWritePtr( dst, dstmax ) );
432 assert( isReadPtr( src, len ) );
433
434 REQUIRES_EXT( ( dstmax > 0 && dstmax < MAX_INTLENGTH_SHORT ), -1 );
435 REQUIRES_EXT( ( len > 0 && len <= dstmax && \
436 len < MAX_INTLENGTH_SHORT ), -1 );
437
438 /* Clear return value */
439 *retval = 0;
440
441 bytesCopied = mbstowcs( dst, src, len );
442 if( ( bytesCopied == ( size_t ) -1 ) || ( bytesCopied <= 0 ) )
443 return( -1 );
444 *retval = bytesCopied;
445 return( 0 );
446 }
447
448 RETVAL_RANGE( -1, 0 ) \
wcstombs_s(OUT size_t * retval,OUT_BUFFER_FIXED (dstmax)char * dst,IN_LENGTH_SHORT size_t dstmax,IN_BUFFER (len)const wchar_t * src,IN_LENGTH_SHORT size_t len)449 int wcstombs_s( OUT size_t *retval,
450 OUT_BUFFER_FIXED( dstmax ) char *dst,
451 IN_LENGTH_SHORT size_t dstmax,
452 IN_BUFFER( len) const wchar_t *src,
453 IN_LENGTH_SHORT size_t len )
454 {
455 size_t bytesCopied;
456
457 assert( isWritePtr( retval, sizeof( size_t ) ) );
458 assert( isWritePtr( dst, dstmax ) );
459 assert( isReadPtr( src, len ) );
460
461 REQUIRES_EXT( ( dstmax > 0 && dstmax < MAX_INTLENGTH_SHORT ), -1 );
462 REQUIRES_EXT( ( len > 0 && len <= dstmax && \
463 len < MAX_INTLENGTH_SHORT ), -1 );
464
465 /* Clear return value */
466 *retval = 0;
467
468 bytesCopied = wcstombs( dst, src, len );
469 if( ( bytesCopied == ( size_t ) -1 ) || ( bytesCopied <= 0 ) )
470 return( -1 );
471 *retval = bytesCopied;
472 return( 0 );
473 }
474 #endif /* !__STDC_LIB_EXT1__ */
475
476 /****************************************************************************
477 * *
478 * Self-test Functions *
479 * *
480 ****************************************************************************/
481
482 /* Test code for the above functions */
483
484 #ifndef NDEBUG
485
486 CHECK_RETVAL_BOOL \
testIntString(void)487 BOOLEAN testIntString( void )
488 {
489 BYTE buffer[ 16 + 8 ];
490 const char *stringPtr;
491 int stringLen, value;
492
493 /* Test strFindCh() */
494 if( strFindCh( "abcdefgh", 8, 'a' ) != 0 || \
495 strFindCh( "abcdefgh", 8, 'd' ) != 3 || \
496 strFindCh( "abcdefgh", 8, 'h' ) != 7 || \
497 strFindCh( "abcdefgh", 8, 'x' ) != -1 )
498 return( FALSE );
499
500 /* Test strFindStr() */
501 if( strFindStr( "abcdefgh", 8, "abc", 3 ) != 0 || \
502 strFindStr( "abcdefgh", 8, "fgh", 3 ) != 5 || \
503 strFindStr( "abcdefgh", 8, "ghi", 3 ) != -1 || \
504 strFindStr( "abcdefgh", 8, "abcdefghi", 9 ) != -1 )
505 return( FALSE );
506
507 /* Test strSkipWhitespace() */
508 if( strSkipWhitespace( "abcdefgh", 8 ) != 0 || \
509 strSkipWhitespace( " abcdefgh", 9 ) != 1 || \
510 strSkipWhitespace( " \t abcdefgh", 11 ) != 3 || \
511 strSkipWhitespace( " x abcdefgh", 11 ) != 1 || \
512 strSkipWhitespace( " \t ", 4 ) != -1 )
513 return( FALSE );
514
515 /* Test strSkipNonWhitespace() */
516 if( strSkipNonWhitespace( "abcdefgh", 8 ) != 8 || \
517 strSkipNonWhitespace( " abcdefgh", 9 ) != -1 || \
518 strSkipNonWhitespace( "abcdefgh ", 9 ) != 8 || \
519 strSkipNonWhitespace( "abcdefgh x ", 11 ) != 8 )
520 return( FALSE );
521
522 /* Test strStripWhitespace() */
523 stringLen = strStripWhitespace( &stringPtr, "abcdefgh", 8 );
524 if( stringLen != 8 || memcmp( stringPtr, "abcdefgh", 8 ) )
525 return( FALSE );
526 stringLen = strStripWhitespace( &stringPtr, " abcdefgh", 9 );
527 if( stringLen != 8 || memcmp( stringPtr, "abcdefgh", 8 ) )
528 return( FALSE );
529 stringLen = strStripWhitespace( &stringPtr, "abcdefgh ", 9 );
530 if( stringLen != 8 || memcmp( stringPtr, "abcdefgh", 8 ) )
531 return( FALSE );
532 stringLen = strStripWhitespace( &stringPtr, " abcdefgh ", 10 );
533 if( stringLen != 8 || memcmp( stringPtr, "abcdefgh", 8 ) )
534 return( FALSE );
535 stringLen = strStripWhitespace( &stringPtr, " x abcdefgh ", 12 );
536 if( stringLen != 10 || memcmp( stringPtr, "x abcdefgh", 10 ) )
537 return( FALSE );
538 stringLen = strStripWhitespace( &stringPtr, " abcdefgh x ", 12 );
539 if( stringLen != 10 || memcmp( stringPtr, "abcdefgh x", 10 ) )
540 return( FALSE );
541 stringLen = strStripWhitespace( &stringPtr, " \t ", 4 );
542 if( stringLen != -1 || stringPtr != NULL )
543 return( FALSE );
544
545 /* Test strExtract() */
546 stringLen = strExtract( &stringPtr, "abcdefgh", 4, 8 );
547 if( stringLen != 4 || memcmp( stringPtr, "efgh", 4 ) )
548 return( FALSE );
549 stringLen = strExtract( &stringPtr, "abcd efgh", 4, 10 );
550 if( stringLen != 4 || memcmp( stringPtr, "efgh", 4 ) )
551 return( FALSE );
552 stringLen = strExtract( &stringPtr, "abcd efgh ", 4, 12 );
553 if( stringLen != 4 || memcmp( stringPtr, "efgh", 4 ) )
554 return( FALSE );
555 stringLen = strExtract( &stringPtr, "abcd efgh ij ", 4, 16 );
556 if( stringLen != 8 || memcmp( stringPtr, "efgh ij", 8 ) )
557 return( FALSE );
558
559
560 /* Test strGetNumeric() */
561 if( strGetNumeric( "0", 1, &value, 0, 10 ) != CRYPT_OK || value != 0 || \
562 strGetNumeric( "00", 2, &value, 0, 10 ) != CRYPT_OK || value != 0 || \
563 strGetNumeric( "1234", 4, &value, 0, 2000 ) != CRYPT_OK || value != 1234 || \
564 strGetNumeric( "1234x", 5, &value, 0, 2000 ) != CRYPT_ERROR_BADDATA || value != 0 || \
565 strGetNumeric( "x1234", 5, &value, 0, 2000 ) != CRYPT_ERROR_BADDATA || value != 0 || \
566 strGetNumeric( "1000", 4, &value, 0, 1000 ) != CRYPT_OK || value != 1000 || \
567 strGetNumeric( "1001", 4, &value, 0, 1000 ) != CRYPT_ERROR_BADDATA || value != 0 )
568 return( FALSE );
569
570 /* Test strGetHex() */
571 if( strGetHex( "0", 1, &value, 0, 1000 ) != CRYPT_OK || value != 0 || \
572 strGetHex( "1234", 4, &value, 0, 0x2000 ) != CRYPT_OK || value != 0x1234 || \
573 strGetHex( "1234x", 5, &value, 0, 0x2000 ) != CRYPT_ERROR_BADDATA || value != 0 || \
574 strGetHex( "x1234", 5, &value, 0, 0x2000 ) != CRYPT_ERROR_BADDATA || value != 0 || \
575 strGetHex( "12EE", 4, &value, 0, 0x12EE ) != CRYPT_OK || value != 0x12EE || \
576 strGetHex( "12EF", 4, &value, 0, 0x12EE ) != CRYPT_ERROR_BADDATA || value != 0 )
577 return( FALSE );
578
579 /* Test sanitiseString() */
580 memcpy( buffer, "abcdefgh", 8 );
581 stringPtr = sanitiseString( buffer, 16, 8 );
582 if( memcmp( stringPtr, "abcdefgh", 9 ) )
583 return( FALSE );
584 memcpy( buffer, "abc\x12" "efgh", 8 );
585 stringPtr = sanitiseString( buffer, 16, 8 );
586 if( memcmp( stringPtr, "abc.efgh", 9 ) )
587 return( FALSE );
588 memcpy( buffer, "abcdefgh", 8 );
589 stringPtr = sanitiseString( buffer, 7, 8 );
590 if( memcmp( stringPtr, "abcdef", 7 ) )
591 return( FALSE );
592 memcpy( buffer, "abcdefgh", 8 );
593 stringPtr = sanitiseString( buffer, 8, 8 );
594 if( memcmp( stringPtr, "abcdefg", 8 ) )
595 return( FALSE );
596 memcpy( buffer, "abcdefghij", 10 );
597 stringPtr = sanitiseString( buffer, 9, 10 );
598 if( memcmp( stringPtr, "abc[...]", 9 ) )
599 return( FALSE );
600 memcpy( buffer, "abcdefghij", 10 );
601 stringPtr = sanitiseString( buffer, 10, 10 );
602 if( memcmp( stringPtr, "abcd[...]", 10 ) )
603 return( FALSE );
604 memcpy( buffer, "abcdefghij", 10 );
605 stringPtr = sanitiseString( buffer, 11, 10 );
606 if( memcmp( stringPtr, "abcdefghij", 11 ) )
607 return( FALSE );
608
609 return( TRUE );
610 }
611 #endif /* !NDEBUG */
612