1 /* -*- mode: c; c-file-style:"stroustrup"; -*- */
2 
3 /*
4  * Copyright (c) 2018 Mastercard
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *   http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <config.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <ctype.h>
25 #include "pkcs11lib.h"
26 
27 static CK_ATTRIBUTE_PTR new_attribute_for_bool(CK_ATTRIBUTE_TYPE argattrtype, CK_BBOOL argval);
28 static CK_ATTRIBUTE_PTR new_attribute_for_string(CK_ATTRIBUTE_TYPE argattrtype, char *arg);
29 static CK_ATTRIBUTE_PTR new_attribute_for_null_term_string(CK_ATTRIBUTE_TYPE argattrtype, char *arg);
30 static CK_ATTRIBUTE_PTR new_attribute_for_hex_string(CK_ATTRIBUTE_TYPE argattrtype, char *arg);
31 
pkcs11_prompt(char * prompt,CK_BBOOL echo)32 char * pkcs11_prompt( char * prompt, CK_BBOOL echo )
33 {
34     char * buf = NULL;
35     char * res = NULL;
36     int n;
37 
38     if ( ( buf = (char *) malloc( sizeof( char ) * MAXBUFSIZE ) ) == NULL )
39     {
40 	fprintf( stderr, "Error: Unable to allocate system memory, exiting.\n" );
41 	exit( RC_ERROR_MEMORY );
42     }
43 
44     fprintf( stderr, "\n%s", prompt );
45     fflush( stdout );
46 
47     if ( !echo ) {
48 	pkcs11_ll_echo_off();
49     }
50 
51     if ( ( res = fgets( buf, MAXBUFSIZE, stdin ) ) == NULL )
52     {
53 	fprintf( stderr, "Error: Unable to read input, exiting.\n" );
54 	exit( RC_ERROR_READ_INPUT );
55     }
56 
57     n = strlen( res );
58 
59     while ( buf[n - 1] != '\n' )
60     {
61 	if ( ( buf = ( char * ) realloc( buf, n + MAXBUFSIZE ) ) == NULL )
62 	{
63 	    fprintf( stderr, "Error: Unable to allocate system memory, exiting\n" );
64 	    exit( RC_ERROR_MEMORY );
65 	}
66 
67 	if ( ( res = fgets( buf + n, MAXBUFSIZE, stdin ) ) == NULL )
68 	{
69 	    fprintf( stderr, "Error: Unable to read input, exiting.\n" );
70 	    exit( RC_ERROR_READ_INPUT );
71 	}
72 
73 	n += strlen( res );
74     }
75 
76     buf[ n -1 ] = 0;
77 
78     if ( !echo )
79     {
80 	pkcs11_ll_echo_on();
81     }
82 
83     printf("\n" );
84     return buf;
85 }
86 
pkcs11_prompt_free_buffer(char * arg)87 void pkcs11_prompt_free_buffer(char *arg)
88 {
89     if(arg) free(arg);
90 }
91 
92 
pkcs11_pipe_password(char * passwordexec)93 char * pkcs11_pipe_password( char * passwordexec )
94 {
95     char * buf = NULL;
96 
97     if(passwordexec!=NULL && strncmp(PASSWORD_EXEC, passwordexec, strlen(PASSWORD_EXEC))==0 ) {
98 
99 	size_t len=0, actual;
100 	FILE * exec_pipe = popen (&passwordexec[strlen(PASSWORD_EXEC)], "r");
101 
102 	if(exec_pipe != NULL) {
103 	    actual = getline(&buf, &len, exec_pipe); /* password is allocated here */
104 	    pclose(exec_pipe);	/* close the pipe */
105 	    if(buf[actual-1]=='\n') { buf[actual-1]=0x0; } /* clear line feed if found */
106 	}
107 
108 
109     }
110 
111     return buf;
112 }
113 
114 
115 /*--------------------------------------------------------------------*/
116 
117 
print_keyClass(CK_ULONG keyClass)118 char * print_keyClass( CK_ULONG keyClass )
119 {
120     char * rv = NULL;
121 
122     switch ( keyClass )
123     {
124     case CKO_DATA :
125 	rv = "CKO_DATA";
126 	break;
127 
128     case CKO_CERTIFICATE :
129 	rv = "CKO_CERTIFICATE";
130 	break;
131 
132     case CKO_PUBLIC_KEY :
133 	rv = "CKO_PUBLIC_KEY";
134 	break;
135 
136     case CKO_PRIVATE_KEY :
137 	rv = "CKO_PRIVATE_KEY";
138 	break;
139 
140     case CKO_SECRET_KEY :
141 	rv = "CKO_SECRET_KEY";
142 	break;
143 
144     case CKO_HW_FEATURE :
145 	rv = "CKO_HW_FEATURE";
146 	break;
147 
148     case CKO_DOMAIN_PARAMETERS :
149 	rv = "CKO_DOMAIN_PARAMETERS";
150 	break;
151 
152     case CKO_MECHANISM :
153 	rv = "CKO_MECHANISM";
154 	break;
155     }
156     return rv;
157 }
158 
get_object_class(char * arg)159 CK_ULONG get_object_class(char *arg)
160 {
161     CK_ULONG class = 0;
162 
163     if (strcasecmp(arg, "CKO_CERTIFICATE")==0) {
164 	class = CKO_CERTIFICATE;
165     } else if (strcasecmp(arg, "CKO_PUBLIC_KEY")==0) {
166 	class = CKO_PUBLIC_KEY;
167     } else if (strcasecmp(arg, "CKO_PRIVATE_KEY")==0) {
168 	class = CKO_PRIVATE_KEY;
169     } else if (strcasecmp(arg, "CKO_SECRET_KEY")==0) {
170 	class = CKO_SECRET_KEY;
171     }
172 
173     return class;
174 }
175 
176 
get_attribute_type(char * arg)177 CK_ATTRIBUTE_TYPE get_attribute_type(char *arg)
178 {
179     CK_ATTRIBUTE_TYPE attrtype = 0xFFFFFFFF;
180 
181     if (strcasecmp(arg, "CKA_ID")==0 || strcasecmp(arg, "ID")==0) {
182 	attrtype = CKA_ID;
183     } else if (strcasecmp(arg, "CKA_LABEL")==0 || strcasecmp(arg, "LABEL")==0) {
184 	attrtype = CKA_LABEL;
185     } else if (strcasecmp(arg, "CKA_WRAP")==0 || strcasecmp(arg, "WRAP")==0) {
186 	attrtype = CKA_WRAP;
187     } else if (strcasecmp(arg, "CKA_UNWRAP")==0 || strcasecmp(arg, "UNWRAP")==0) {
188 	attrtype = CKA_UNWRAP;
189     } else if (strcasecmp(arg, "CKA_ENCRYPT")==0 || strcasecmp(arg, "ENCRYPT")==0) {
190 	attrtype = CKA_ENCRYPT;
191     } else if (strcasecmp(arg, "CKA_DECRYPT")==0 || strcasecmp(arg, "DECRYPT")==0) {
192 	attrtype = CKA_DECRYPT;
193     } else if (strcasecmp(arg, "CKA_SIGN")==0 || strcasecmp(arg, "SIGN")==0) {
194 	attrtype = CKA_SIGN;
195     } else if (strcasecmp(arg, "CKA_VERIFY")==0 || strcasecmp(arg, "VERIFY")==0) {
196 	attrtype = CKA_VERIFY;
197     } else if (strcasecmp(arg, "CKA_SIGN_RECOVER")==0 || strcasecmp(arg, "SIGN_RECOVER")==0) {
198 	attrtype = CKA_SIGN_RECOVER;
199     } else if (strcasecmp(arg, "CKA_VERIFY_RECOVER")==0 || strcasecmp(arg, "VERIFY_RECOVER")==0) {
200 	attrtype = CKA_VERIFY_RECOVER;
201     } else if (strcasecmp(arg, "CKA_DERIVE")==0 || strcasecmp(arg, "DERIVE")==0) {
202 	attrtype = CKA_DERIVE;
203     } else if (strcasecmp(arg, "CKA_TRUSTED")==0 || strcasecmp(arg, "TRUSTED")==0) {
204 	attrtype = CKA_TRUSTED;
205     } else if (strcasecmp(arg, "CKA_WRAP_WITH_TRUSTED")==0 || strcasecmp(arg, "WRAP_WITH_TRUSTED")==0) {
206 	attrtype = CKA_WRAP_WITH_TRUSTED;
207     } else if (strcasecmp(arg, "CKA_MODIFIABLE")==0 || strcasecmp(arg, "MODIFIABLE")==0) {
208 	attrtype = CKA_MODIFIABLE;
209     } else if (strcasecmp(arg, "CKA_EXTRACTABLE")==0 || strcasecmp(arg, "EXTRACTABLE")==0) {
210 	attrtype = CKA_EXTRACTABLE;
211     } else if (strcasecmp(arg, "CKA_SENSITIVE")==0 || strcasecmp(arg, "SENSITIVE")==0) {
212 	attrtype = CKA_SENSITIVE;
213 	/* EC attributes */
214     } else if (strcasecmp(arg, "CKA_EC_PARAMS")==0 || strcasecmp(arg, "EC_PARAMS")==0) {
215 	attrtype = CKA_EC_PARAMS;
216     	/* NSS attributes */
217     } else if (strcasecmp(arg, "CKA_TRUST_SERVER_AUTH")==0 || strcasecmp(arg, "TRUST_SERVER_AUTH")==0) {
218 	attrtype = CKA_TRUST_SERVER_AUTH;
219     } else if (strcasecmp(arg, "CKA_TRUST_CLIENT_AUTH")==0 || strcasecmp(arg, "TRUST_CLIENT_AUTH")==0) {
220 	attrtype = CKA_TRUST_CLIENT_AUTH;
221     } else if (strcasecmp(arg, "CKA_TRUST_CODE_SIGNING")==0 || strcasecmp(arg, "TRUST_CODE_SIGNING")==0) {
222 	attrtype = CKA_TRUST_CODE_SIGNING;
223     } else if (strcasecmp(arg, "CKA_TRUST_EMAIL_PROTECTION")==0 || strcasecmp(arg, "TRUST_EMAIL_PROTECTION")==0) {
224 	attrtype = CKA_TRUST_EMAIL_PROTECTION;
225     }
226 
227     return attrtype;
228 }
229 
230 
new_attribute_for_bool(CK_ATTRIBUTE_TYPE argattrtype,CK_BBOOL argval)231 static CK_ATTRIBUTE_PTR new_attribute_for_bool(CK_ATTRIBUTE_TYPE argattrtype, CK_BBOOL argval)
232 {
233     CK_ATTRIBUTE_PTR attr = NULL;
234 
235     attr = malloc ( sizeof ( CK_ATTRIBUTE ) );
236 
237     if ( attr != NULL ) {
238 	CK_BBOOL* boolptr = malloc ( sizeof ( CK_BBOOL ) );
239 
240 	if ( boolptr != NULL ) {
241 	    *boolptr = argval;	/* copy the value we received */
242 	    attr->type = argattrtype;
243 	    attr->pValue = boolptr;
244 	    attr->ulValueLen = sizeof( CK_BBOOL );
245 	} else {
246 	    fprintf( stderr, "Error: lack of memory\n");
247 	    free( attr);
248 	}
249     } else {
250 	fprintf( stderr, "Error: lack of memory\n");
251     }
252 
253     return attr;
254 }
255 
new_attribute_for_string(CK_ATTRIBUTE_TYPE argattrtype,char * arg)256 CK_ATTRIBUTE_PTR new_attribute_for_string(CK_ATTRIBUTE_TYPE argattrtype, char *arg)
257 {
258     if(strchr(arg, '{' ) && strrchr(arg, '}')) {
259 	/* we have an hex string */
260 	return new_attribute_for_hex_string( argattrtype, arg);
261     } else {
262 	return new_attribute_for_null_term_string( argattrtype, arg);
263     }
264 }
265 
new_attribute_for_null_term_string(CK_ATTRIBUTE_TYPE argattrtype,char * arg)266 CK_ATTRIBUTE_PTR new_attribute_for_null_term_string(CK_ATTRIBUTE_TYPE argattrtype, char *arg)
267 {
268     CK_ATTRIBUTE_PTR attr = NULL;
269 
270     attr = calloc ( 1, sizeof ( CK_ATTRIBUTE ) );
271 
272     if ( attr != NULL ) {
273 	char *strptr = calloc ( strlen(arg)+1, sizeof (char) );
274 
275 	if ( strptr != NULL ) {
276 	    strcpy(strptr, arg);
277 
278 	    attr->type = argattrtype;
279 	    attr->pValue = strptr;
280 	    attr->ulValueLen = strlen(arg); /* we stop at character's end */
281 	} else {
282 	    fprintf( stderr, "Error: lack of memory\n");
283 	    free(attr);
284 	}
285     } else {
286 	fprintf( stderr, "Error: lack of memory\n");
287     }
288 
289     return attr;
290 }
291 
new_attribute_for_hex_string(CK_ATTRIBUTE_TYPE argattrtype,char * arg)292 CK_ATTRIBUTE_PTR new_attribute_for_hex_string(CK_ATTRIBUTE_TYPE argattrtype, char *arg)
293 {
294     CK_ATTRIBUTE_PTR attr = NULL;
295 
296     attr = calloc ( 1, sizeof ( CK_ATTRIBUTE ) );
297 
298     if ( attr != NULL ) {
299 	size_t outsize=0;
300 	char *hexstr = hex2bin_new( arg, strlen(arg), &outsize);
301 
302 	if ( hexstr != NULL ) {
303 
304 	    char *dupstr = malloc(outsize);
305 
306 	    if ( dupstr != NULL ) {
307 		memcpy(dupstr,hexstr,outsize);
308                 /* duplicate buffer */
309 		/* and assign it */
310 		attr->type = argattrtype;
311 		attr->pValue = dupstr;
312 		attr->ulValueLen = outsize;
313 	    } else {
314 		fprintf( stderr, "Error: lack of memory\n");
315 		free(attr);
316 	    }
317 	    hex2bin_free(hexstr);	       /* free buf in any case */
318 
319 	} else {
320 	    fprintf( stderr, "Error: lack of memory\n");
321 	    free(attr);
322 	}
323     } else {
324 	fprintf( stderr, "Error: lack of memory\n");
325     }
326 
327     return attr;
328 }
329 
330 
hex2bin_new(char * label,size_t size,size_t * outsize)331 char * hex2bin_new(char *label, size_t size, size_t *outsize)
332 {
333 
334     char *pos, *initpos;
335     char *tmpbuf=NULL, *tmpbuf_s=NULL;
336     char *target;
337     size_t len;
338     size_t ws_cnt, i;
339 
340 
341     /* since there can be decoration characters in the input string, */
342     /* and since the resulting hex chars can be an odd number */
343     /* we first pass to count decoration chars,  */
344     /* then we allocate buffer and prepend with a '0' if odd, */
345     /* then we copy significant characters. */
346 
347     /* #1: count the number of decoration chars in the string */
348     /*     see regular expression definition in calling function */
349     /*     for the definition of a decoration character */
350 
351     for (i=0, ws_cnt=0; i<size; i++) {
352 	if( !isxdigit(label[i]) ) {
353 	    /* TODO: check if we indeed have a decorator character */
354 	    /*       to detect hex strings containing other alphabet letters */
355 	    ws_cnt++;
356 	}
357     }
358 
359     /* #2: allocate tmpbuf with right size and prepend with a leading '0' if needed */
360     len = (size-ws_cnt)+ ((size-ws_cnt)%2);
361     tmpbuf = calloc(sizeof(char), len+1);
362 
363     tmpbuf_s=tmpbuf;
364 
365     if((size-ws_cnt)%2) {		/* odd length, we need to prepend with a '0' */
366 	*tmpbuf_s++='0';
367     }
368 
369     /* #3: copy characters, but skip whitespaces */
370     for (i=0; i<size; i++) {
371 	if( isxdigit(label[i]) ) {
372 	    *tmpbuf_s++=label[i];
373 	}
374     }
375 
376     /* #4: output buffer determination */
377     *outsize = len >> 1;
378     target = malloc( *outsize );
379 
380     /* #5: scan resulting set and conversion */
381     for( initpos = pos = tmpbuf; *pos && (pos-initpos < len); ++pos)
382     {
383 	if( !((pos-initpos)&1) ) {
384 	    sscanf(pos,"%2hhx", &target[(pos-initpos)>>1]);
385 	}
386     }
387 
388     if(tmpbuf) {
389 	free(tmpbuf);
390     }
391 
392     return target;
393 
394 }
395 
hex2bin_free(char * ptr)396 void hex2bin_free(char *ptr)
397 {
398     if(ptr) {
399 	free(ptr);
400     }
401 }
402 
get_attribute_for_type_and_value(CK_ATTRIBUTE_TYPE argattrtype,char * arg)403 CK_ATTRIBUTE_PTR get_attribute_for_type_and_value(CK_ATTRIBUTE_TYPE argattrtype, char *arg )
404 {
405     CK_ATTRIBUTE_PTR attr = NULL;
406 
407     switch(argattrtype) {
408     case CKA_WRAP:
409     case CKA_UNWRAP:
410     case CKA_ENCRYPT:
411     case CKA_DECRYPT:
412     case CKA_SIGN:
413     case CKA_VERIFY:
414     case CKA_SIGN_RECOVER:
415     case CKA_VERIFY_RECOVER:
416     case CKA_DERIVE:
417     case CKA_TRUSTED:
418     case CKA_WRAP_WITH_TRUSTED:
419     case CKA_MODIFIABLE:
420     case CKA_EXTRACTABLE:
421     case CKA_SENSITIVE:
422 	/* NSS-specific */
423     case CKA_TRUST_SERVER_AUTH:
424     case CKA_TRUST_CLIENT_AUTH:
425     case CKA_TRUST_CODE_SIGNING:
426     case CKA_TRUST_EMAIL_PROTECTION:
427     {
428 	CK_BBOOL val;
429 
430 	if ( strcasecmp(arg, "true")==0 || strcasecmp(arg, "yes")==0 || strcasecmp(arg, "1")==0 ) {
431 	    val = CK_TRUE;
432 	    attr = new_attribute_for_bool( argattrtype, val);
433 	} else if ( strcasecmp(arg, "false")==0 || strcasecmp(arg, "no")==0 || strcasecmp(arg,"0")==0) {
434 	    val = CK_FALSE;
435 	    attr = new_attribute_for_bool( argattrtype, val);
436 	} else {
437 	    fprintf(stderr, "Error: value for boolean attribute must be either TRUE or FALSE\n");
438 	}
439     }
440     break;
441 
442     case CKA_ID:
443     case CKA_LABEL:
444 	attr = new_attribute_for_string(argattrtype, arg);
445 	break;
446 
447     default:
448 	fprintf( stderr, "please specify an attribute type before giving a value");
449     }
450 
451     return attr;
452 }
453 
454 
print_keyType(CK_ULONG keyType)455 char * print_keyType( CK_ULONG keyType )
456 {
457     switch( keyType )
458     {
459     case CKK_AES :
460 	return "CKK_AES";
461     case CKK_DES :
462 	return "CKK_DES";
463     case CKK_DES3 :
464 	return "CKK_DES3";
465     case CKK_RSA :
466 	return "CKK_RSA";
467     case CKK_GENERIC_SECRET :
468 	return "CKK_GENERIC_SECRET";
469 #ifdef CKK_SHA_1_HMAC
470     case CKK_SHA_1_HMAC :
471 	return "CKK_SHA_1_HMAC";
472 #endif
473     default :
474 	return "CKK_VENDOR_DEFINED";
475     }
476 }
477 
478 
479 
get_attributes_from_argv(CK_ATTRIBUTE * attrs[],int pos,int argc,char ** argv)480 int get_attributes_from_argv( CK_ATTRIBUTE *attrs[] , int pos, int argc, char **argv)
481 {
482 
483     int i;
484     char *cpy = NULL;
485     int rv = 0;
486     int cnt = 0;
487 
488     for (i=pos; i<argc; ++i) {
489 	char *a, *v;
490 	CK_ATTRIBUTE_TYPE typ;
491 	CK_ATTRIBUTE_PTR  val;
492 
493 	if((cpy = malloc( strlen(argv[i]) + 1 )) == NULL ) {
494 	    fprintf(stderr,"Error: can't allocate memory\n");
495 	    goto err;
496 	}
497 	strcpy(cpy, argv[i]);
498 
499 	a = strtok(cpy, ":=");
500 	if(a==NULL) {
501 	    fprintf(stderr, "Error: argument ""%s"" contains no separator ( : or = )\n", argv[i]);
502 	    goto err;
503 	}
504 
505 	typ = get_attribute_type(a);
506 	if(typ==0xFFFFFFFF) {
507 	    fprintf(stderr, "Error: unknown attribute type ""%s""\n", a);
508 	    goto err;
509 
510 	}
511 
512 	v = strtok(NULL, ":=");
513 
514 	if(v==NULL) {
515 	    fprintf(stderr, "Error: argument ""%s"" has no value\n", argv[i]);
516 	    goto err;
517 	}
518 	val = get_attribute_for_type_and_value(typ, v);
519 
520 	if(val==NULL) {
521 	    fprintf(stderr, "Error: wrong attribute value ""%s""\n", v);
522 	    goto err;
523 	}
524 
525 	release_attribute(val); val=NULL;
526 	free(cpy); cpy=NULL;
527 
528 	cnt++;
529     }
530 
531 
532     /* now allocate array of attributes */
533     if(cnt==0) {
534 	fprintf(stderr, "Error: no attribute-value pair argument specified\n");
535 	goto err;
536     }
537 
538     *attrs = calloc( cnt, sizeof(CK_ATTRIBUTE) ); /* allocate from heap */
539 
540     if(*attrs == NULL) {
541 	fprintf(stderr, "Error: can't allocate memory\n");
542 	goto err;
543     }
544 
545 
546     for(i=pos; i<argc; i++) {
547 	char *a, *v;
548 	CK_ATTRIBUTE_PTR item;
549 
550 	a = strtok(argv[i], ":=");
551 	v = strtok(NULL, ":=");
552 
553 	item = 	get_attribute_for_type_and_value( get_attribute_type(a), v );
554 	memcpy( &((*attrs)[i-pos]), item, sizeof( CK_ATTRIBUTE ) );
555 	item->pValue=NULL;	/* caution! we have moved pValue to the array  */
556 	                        /* we must clear it from the initial structure */
557 	release_attribute(item);
558     }
559 
560     rv = cnt;
561 
562 err:
563     if(cpy) { free(cpy); cpy = NULL; }
564 
565     return rv;
566 }
567 
release_attribute(CK_ATTRIBUTE_PTR arg)568 void release_attribute( CK_ATTRIBUTE_PTR arg)
569 {
570     if(arg) {
571 	if (arg->pValue) {
572 	    free(arg->pValue);
573 	}
574 	free(arg);
575     }
576 }
577 
578 
release_attributes(CK_ATTRIBUTE attrs[],size_t cnt)579 void release_attributes(CK_ATTRIBUTE attrs[], size_t cnt)
580 {
581     if(attrs) {
582 	int i;
583 
584 	for(i=0; i<cnt; i++) {
585 	    CK_ATTRIBUTE_PTR item = &attrs[i];
586 	    if (item->pValue) {
587 		free(item->pValue);
588 	    }
589 	}
590 
591 	free(attrs);		/* free table, eventually */
592     }
593 }
594 
prompt_for_hex(char * message,char * prompt,char * target,int len)595 func_rc prompt_for_hex(char *message, char *prompt, char *target, int len)
596 {
597     func_rc rc = RC_OK;
598 
599     char *spacer  = "                                                                ";
600     char *helper1 = "00                11                  22                  33    ";
601     char *helper2 = "1122334455667788990011223344556677889900112233445566778899001122";
602 
603     char *buf=NULL, *pos;
604     size_t buf_len=0;
605 
606     if(message && prompt && target &&  len>0) {
607 
608 	int prompt_len = strlen(prompt);
609 
610 	printf("%s\n\n%.*s%.*s\n%.*s%.*s\n%s ",
611 	       message,
612 	       prompt_len+1, spacer, len<<1, helper1,
613 	       prompt_len+1, spacer, len<<1, helper2,
614 	       prompt);
615 
616 	fflush(stdout);
617 
618 	getline(&buf, &buf_len, stdin); /* buffer is allocated */
619 
620 	pos = buf;
621 	while( *pos )
622 	{
623 	    unsigned int x;
624 	    if( !((pos-buf)&1) ) {
625 		if (((pos-buf)>>1) == len ) break;
626 		/* because sscanf returns the value as an unsigned int, */
627 		/* we must pass through type casting to avoid memory/stack overflow */
628 		sscanf(pos,"%02x", &x);
629 		target[(pos-buf)>>1]= (unsigned char)x;
630 	    }
631 	    ++pos;
632 	}
633 
634 	if(buf) free(buf);
635     }
636 
637     return rc;
638 }
639 
640 
641 
642 
643 
644 #define MAXOF(x,y) ((x)>(y)) ? (x) : (y)
645 #define MINOF(x,y) ((x)<(y)) ? (x) : (y)
646 
647 #define UNLABELLED_OBJECT "???unlabelled object???"
648 
label_or_id(CK_ATTRIBUTE_PTR label,CK_ATTRIBUTE_PTR id,char * buffer,int buffer_len)649 char * label_or_id(CK_ATTRIBUTE_PTR label, CK_ATTRIBUTE_PTR id, char *buffer, int buffer_len)
650 {
651     if(label && label->ulValueLen>0) {	/* we have a label, let's use it */
652 	/* label is NEVER null terminated */
653 	/* we cannot use strncpy */
654 	memcpy( buffer, label->pValue,  MINOF(buffer_len-1,label->ulValueLen));
655 	buffer[ MINOF(buffer_len-1,label->ulValueLen) ] = 0; /* terminate the string */
656     } else if(id && id->ulValueLen>0) { /* we have no label apparently */
657 	char *hexidptr = buffer;
658 	CK_BYTE_PTR idptr = id->pValue;
659 	CK_ULONG idcnt=0;
660 
661 	*hexidptr++='i';
662 	*hexidptr++='d';
663 	*hexidptr++='/';
664 	*hexidptr++='{';
665 	idptr = (CK_BYTE_PTR)id->pValue;
666 
667 	while(hexidptr-buffer<(buffer_len - 2) && idcnt<id->ulValueLen) {
668 	    sprintf(hexidptr,"%2.2x", idptr[idcnt++]);
669 	    hexidptr+=2;
670 	}
671 	*hexidptr++='}';
672 	*hexidptr='\0';
673     } else {			/* no id or label */
674 	strncpy(buffer, UNLABELLED_OBJECT , MINOF(buffer_len-1, strlen(UNLABELLED_OBJECT)));
675 	buffer[ MINOF(buffer_len-1, strlen(UNLABELLED_OBJECT)) ] = 0; /* terminate string */
676     }
677 
678     return buffer;
679 }
680 
681 
682 /*
683  *--------------------------------------------------------------------------------
684  * $Log$
685  *--------------------------------------------------------------------------------
686  */
687