1 /********************************************************************************/
2 /*										*/
3 /*			     TSS Library Independent Crypto Support		*/
4 /*			     Written by Ken Goldman				*/
5 /*		       IBM Thomas J. Watson Research Center			*/
6 /*										*/
7 /* (c) Copyright IBM Corporation 2015 - 2019.					*/
8 /*										*/
9 /* All rights reserved.								*/
10 /* 										*/
11 /* Redistribution and use in source and binary forms, with or without		*/
12 /* modification, are permitted provided that the following conditions are	*/
13 /* met:										*/
14 /* 										*/
15 /* Redistributions of source code must retain the above copyright notice,	*/
16 /* this list of conditions and the following disclaimer.			*/
17 /* 										*/
18 /* Redistributions in binary form must reproduce the above copyright		*/
19 /* notice, this list of conditions and the following disclaimer in the		*/
20 /* documentation and/or other materials provided with the distribution.		*/
21 /* 										*/
22 /* Neither the names of the IBM Corporation nor the names of its		*/
23 /* contributors may be used to endorse or promote products derived from		*/
24 /* this software without specific prior written permission.			*/
25 /* 										*/
26 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS		*/
27 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT		*/
28 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR	*/
29 /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT		*/
30 /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,	*/
31 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT		*/
32 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,	*/
33 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY	*/
34 /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT		*/
35 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE	*/
36 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.		*/
37 /********************************************************************************/
38 
39 #include <string.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <stdarg.h>
43 
44 #ifdef TPM_POSIX
45 #include <netinet/in.h>
46 #endif
47 #ifdef TPM_WINDOWS
48 #include <winsock2.h>
49 #endif
50 
51 #include <ibmtss/tssresponsecode.h>
52 #include <ibmtss/tssutils.h>
53 #include <ibmtss/tssprint.h>
54 #include <ibmtss/tsserror.h>
55 
56 #include <ibmtss/tsscryptoh.h>
57 #include <ibmtss/tsscrypto.h>
58 
59 extern int tssVverbose;
60 extern int tssVerbose;
61 
62 /* local prototypes */
63 
64 static TPM_RC TSS_MGF1(unsigned char       	*mask,
65 		       uint32_t            	maskLen,
66 		       const unsigned char 	*mgfSeed,
67 		       uint16_t			mgfSeedlen,
68 		       TPMI_ALG_HASH 		halg);
69 
70 /* TSS_HMAC_Generate() can be called directly to HMAC a list of streams.
71 
72    The ... arguments are a message list of the form
73    int length, unsigned char *buffer
74    terminated by a 0 length
75 */
76 
77 /* On call, digest->hashAlg is the desired hash algorithm */
78 
TSS_HMAC_Generate(TPMT_HA * digest,const TPM2B_KEY * hmacKey,...)79 TPM_RC TSS_HMAC_Generate(TPMT_HA *digest,		/* largest size of a digest */
80 			 const TPM2B_KEY *hmacKey,
81 			 ...)
82 {
83     TPM_RC		rc = 0;
84     va_list		ap;
85 
86     va_start(ap, hmacKey);
87     rc = TSS_HMAC_Generate_valist(digest, hmacKey, ap);
88     va_end(ap);
89     return rc;
90 }
91 
92 /* TSS_HMAC_Verify() can be called directly to check the HMAC of a list of streams.
93 
94    The ... arguments are a list of the form
95    int length, unsigned char *buffer
96    terminated by a 0 length
97 
98 */
99 
TSS_HMAC_Verify(TPMT_HA * expect,const TPM2B_KEY * hmacKey,uint32_t sizeInBytes,...)100 TPM_RC TSS_HMAC_Verify(TPMT_HA *expect,
101 		       const TPM2B_KEY *hmacKey,
102 		       uint32_t sizeInBytes,
103 		       ...)
104 {
105     TPM_RC		rc = 0;
106     int			irc;
107     va_list		ap;
108     TPMT_HA 		actual;
109 
110     actual.hashAlg = expect->hashAlg;	/* algorithm for the HMAC calculation */
111     va_start(ap, sizeInBytes);
112     if (rc == 0) {
113 	rc = TSS_HMAC_Generate_valist(&actual, hmacKey, ap);
114     }
115     if (rc == 0) {
116 	irc = memcmp((uint8_t *)&expect->digest, &actual.digest, sizeInBytes);
117 	if (irc != 0) {
118 	    TSS_PrintAll("TSS_HMAC_Verify: calculated HMAC",
119 			 (uint8_t *)&actual.digest, sizeInBytes);
120 	    rc = TSS_RC_HMAC_VERIFY;
121 	}
122     }
123     va_end(ap);
124     return rc;
125 }
126 
127 /* TSS_KDFA() 11.4.9	Key Derivation Function
128 
129    As defined in SP800-108, the inner loop for building the key stream is:
130 
131    K(i) = HMAC (KI , [i]2 || Label || 00 || Context || [L]2)
132 */
133 
TSS_KDFA(uint8_t * keyStream,TPM_ALG_ID hashAlg,const TPM2B * key,const char * label,const TPM2B * contextU,const TPM2B * contextV,uint32_t sizeInBits)134 TPM_RC TSS_KDFA(uint8_t		*keyStream,    	/* OUT: key buffer */
135 		TPM_ALG_ID	hashAlg,       	/* IN: hash algorithm used in HMAC */
136 		const TPM2B	*key,           /* IN: HMAC key */
137 		const char	*label,		/* IN: KDFa label, NUL terminated */
138 		const TPM2B	*contextU,      /* IN: context U */
139 		const TPM2B	*contextV,      /* IN: context V */
140 		uint32_t	sizeInBits)    	/* IN: size of generated key in bits */
141 
142 {
143     TPM_RC	rc = 0;
144     uint32_t 	bytes = ((sizeInBits + 7) / 8);	/* bytes left to produce */
145     uint8_t	*stream;
146     uint32_t 	sizeInBitsNbo = htonl(sizeInBits);	/* KDFa L2 */
147     uint16_t    bytesThisPass;			/* in one HMAC operation */
148     uint32_t	counter;    			/* counter value */
149     uint32_t 	counterNbo;			/* counter in big endian */
150     TPMT_HA 	hmac;				/* hmac result for this pass */
151 
152 
153     if (rc == 0) {
154 	hmac.hashAlg = hashAlg;			/* for TSS_HMAC_Generate() */
155 	bytesThisPass = TSS_GetDigestSize(hashAlg);	/* start with hashAlg sized chunks */
156 	if (bytesThisPass == 0) {
157 	    if (tssVerbose) printf("TSS_KDFA: KDFa failed\n");
158 	    rc = TSS_RC_KDFA_FAILED;
159 	}
160     }
161     /* Generate required bytes */
162     for (stream = keyStream, counter = 1 ;	/* beginning of stream, KDFa counter starts at 1 */
163 	 (rc == 0) && bytes > 0 ;				/* bytes left to produce */
164 	 stream += bytesThisPass, bytes -= bytesThisPass, counter++) {
165 
166 	/* last pass, can be less than hashAlg sized chunks */
167 	if (bytes < bytesThisPass) {
168 	    bytesThisPass = bytes;
169 	}
170 	counterNbo = htonl(counter);	/* counter for this pass in BE format */
171 
172 	rc = TSS_HMAC_Generate(&hmac,				/* largest size of an HMAC */
173 			       (const TPM2B_KEY *)key,
174 			       sizeof(uint32_t), &counterNbo,	/* KDFa i2 counter */
175 			       strlen(label) + 1, label,	/* KDFa label, use NUL as the KDFa
176 								   00 byte */
177 			       contextU->size, contextU->buffer,	/* KDFa Context */
178 			       contextV->size, contextV->buffer,	/* KDFa Context */
179 			       sizeof(uint32_t), &sizeInBitsNbo,	/* KDFa L2 */
180 			       0, NULL);
181 	memcpy(stream, &hmac.digest.tssmax, bytesThisPass);
182     }
183     return rc;
184 }
185 
186 /* TSS_KDFE() 11.4.9.3	Key Derivation Function for ECDH
187 
188    Digest = Hash(counter || Z || Use || PartyUInfo || PartyVInfo || bits )
189 
190    where
191 
192    counter is initialized to 1 and incremented for each iteration
193 
194    Z is the X-coordinate of the product of a public (TPM) ECC key and
195    a different private ECC key
196 
197    Use is a NULL-terminated string that indicates the use of the key
198    ("DUPLICATE", "IDENTITY", "SECRET", etc)
199 
200    PartyUInfo is the X-coordinate of the public point of an ephemeral key
201 
202    PartyVInfo is the X-coordinate of the public point of the TPM key
203 
204    bits is a 32-bit value indicating the number of bits to be returned
205 */
206 
TSS_KDFE(uint8_t * keyStream,TPM_ALG_ID hashAlg,const TPM2B * key,const char * label,const TPM2B * contextU,const TPM2B * contextV,uint32_t sizeInBits)207 TPM_RC TSS_KDFE(uint8_t		*keyStream,    	/* OUT: key buffer */
208 		TPM_ALG_ID	hashAlg,       	/* IN: hash algorithm used */
209 		const TPM2B	*key,           /* IN: Z  */
210 		const char	*label,		/* IN: KDFe label, NUL terminated */
211 		const TPM2B	*contextU,      /* IN: context U */
212 		const TPM2B	*contextV,      /* IN: context V */
213 		uint32_t	sizeInBits)    	/* IN: size of generated key in bits */
214 
215 {
216     TPM_RC	rc = 0;
217     uint32_t 	bytes = ((sizeInBits + 7) / 8);	/* bytes left to produce */
218     uint8_t	*stream;
219     uint16_t    bytesThisPass;			/* in one Hash operation */
220     uint32_t	counter;    			/* counter value */
221     uint32_t 	counterNbo;			/* counter in big endian */
222     TPMT_HA 	digest;				/* result for this pass */
223 
224     if (rc == 0) {
225 	digest.hashAlg = hashAlg;			/* for TSS_Hash_Generate() */
226 	bytesThisPass = TSS_GetDigestSize(hashAlg);	/* start with hashAlg sized chunks */
227 	if (bytesThisPass == 0) {
228 	    if (tssVerbose) printf("TSS_KDFE: KDFe failed\n");
229 	    rc = TSS_RC_KDFE_FAILED;
230 	}
231     }
232     /* Generate required bytes */
233     for (stream = keyStream, counter = 1 ;	/* beginning of stream, KDFe counter starts at 1 */
234 	 (rc == 0) && bytes > 0 ;				/* bytes left to produce */
235 	 stream += bytesThisPass, bytes -= bytesThisPass, counter++) {
236 	/* last pass, can be less than hashAlg sized chunks */
237 	if (bytes < bytesThisPass) {
238 	    bytesThisPass = bytes;
239 	}
240 	counterNbo = htonl(counter);	/* counter for this pass in BE format */
241 
242 	rc = TSS_Hash_Generate(&digest,				/* largest size of a digest */
243 			       sizeof(uint32_t), &counterNbo,	/* KDFe i2 counter */
244 			       key->size, key->buffer,
245 			       strlen(label) + 1, label,	/* KDFe label, use NUL as the KDFe
246 								   00 byte */
247 			       contextU->size, contextU->buffer,	/* KDFe Context */
248 			       contextV->size, contextV->buffer,	/* KDFe Context */
249 			       0, NULL);
250 	memcpy(stream, &digest.digest.tssmax, bytesThisPass);
251     }
252     return rc;
253 }
254 
255 /* On call, digest->hashAlg is the desired hash algorithm
256 
257    ... is a list of int length, unsigned char *buffer pairs.
258 
259    length 0 is ignored, buffer NULL terminates list.
260 */
261 
TSS_Hash_Generate(TPMT_HA * digest,...)262 TPM_RC TSS_Hash_Generate(TPMT_HA *digest,		/* largest size of a digest */
263 			 ...)
264 {
265     TPM_RC	rc = 0;
266     va_list	ap;
267     va_start(ap, digest);
268     rc = TSS_Hash_Generate_valist(digest, ap);
269     va_end(ap);
270     return rc;
271 }
272 
273 
274 /* TSS_GetDigestBlockSize() returns the digest block size in bytes based on the hash algorithm.
275 
276    Returns 0 for an unknown algorithm.
277 */
278 
279 /* NOTE: Marked as const function in header */
280 
TSS_GetDigestBlockSize(TPM_ALG_ID hashAlg)281 uint16_t TSS_GetDigestBlockSize(TPM_ALG_ID hashAlg)
282 {
283     uint16_t size;
284 
285     switch (hashAlg) {
286 #ifdef TPM_ALG_SHA1
287      case TPM_ALG_SHA1:
288 	size = SHA1_BLOCK_SIZE;
289 	break;
290 #endif
291 #ifdef TPM_ALG_SHA256
292       case TPM_ALG_SHA256:
293 	size = SHA256_BLOCK_SIZE;
294 	break;
295 #endif
296 #ifdef TPM_ALG_SHA384
297      case TPM_ALG_SHA384:
298 	size = SHA384_BLOCK_SIZE;
299 	break;
300 #endif
301 #ifdef TPM_ALG_SHA512
302       case TPM_ALG_SHA512:
303 	size = SHA512_BLOCK_SIZE;
304 	break;
305 #endif
306 #if 0
307       case TPM_ALG_SM3_256:
308 	size = SM3_256_BLOCK_SIZE;
309 	break;
310 #endif
311       default:
312 	size = 0;
313     }
314     return size;
315 }
316 
317 /* TPM_MGF1() generates an MGF1 'array' of length 'arrayLen' from 'seed' of length 'seedlen'
318 
319    The openSSL DLL doesn't export MGF1 in Windows or Linux 1.0.0, so this version is created from
320    scratch.
321 
322    Algorithm and comments (not the code) from:
323 
324    PKCS #1: RSA Cryptography Specifications Version 2.1 B.2.1 MGF1
325 
326    Prototype designed to be compatible with openSSL
327 
328    MGF1 is a Mask Generation Function based on a hash function.
329 
330    MGF1 (mgfSeed, maskLen)
331 
332    Options:
333 
334    Hash hash function (hLen denotes the length in octets of the hash
335    function output)
336 
337    Input:
338 
339    mgfSeed         seed from which mask is generated, an octet string
340    maskLen         intended length in octets of the mask, at most 2^32(hLen)
341 
342    Output:
343    mask            mask, an octet string of length l; or "mask too long"
344 
345    Error:          "mask too long'
346 */
347 
TSS_MGF1(unsigned char * mask,uint32_t maskLen,const unsigned char * mgfSeed,uint16_t mgfSeedlen,TPMI_ALG_HASH halg)348 static TPM_RC TSS_MGF1(unsigned char       	*mask,
349 		       uint32_t            	maskLen,
350 		       const unsigned char 	*mgfSeed,
351 		       uint16_t			mgfSeedlen,
352 		       TPMI_ALG_HASH 		halg)
353 {
354     TPM_RC 		rc = 0;
355     unsigned char       counter[4];     /* 4 octets */
356     uint32_t	        count;          /* counter as an integral type */
357     uint32_t		outLen;
358     TPMT_HA 		digest;
359     uint16_t 		digestSize = TSS_GetDigestSize(halg);
360 
361     digest.hashAlg = halg;
362 
363 #if 0
364     if (rc == 0) {
365         /* this is possible with arrayLen on a 64 bit architecture, comment to quiet beam */
366         if ((maskLen / TPM_DIGEST_SIZE) > 0xffffffff) {        /* constant condition */
367             if (tssVerbose)
368 		printf("TSS_MGF1: Error (fatal), Output length too large for 32 bit counter\n");
369             rc = TPM_FAIL;              /* should never occur */
370         }
371     }
372 #endif
373     /* 1.If l > 2^32(hLen), output "mask too long" and stop. */
374     /* NOTE Checked by caller */
375     /* 2. Let T be the empty octet string. */
376     /* 3. For counter from 0 to [masklen/hLen] - 1, do the following: */
377     for (count = 0, outLen = 0 ; (rc == 0) && (outLen < maskLen) ; count++) {
378 	/* a. Convert counter to an octet string C of length 4 octets - see Section 4.1 */
379 	/* C = I2OSP(counter, 4) NOTE Basically big endian */
380         uint32_t count_n = htonl(count);
381 	memcpy(counter, &count_n, 4);
382 	/* b.Concatenate the hash of the seed mgfSeed and C to the octet string T: */
383 	/* T = T || Hash (mgfSeed || C) */
384 	/* If the entire digest is needed for the mask */
385 	if ((outLen + digestSize) < maskLen) {
386 	    rc = TSS_Hash_Generate(&digest,
387 				   mgfSeedlen, mgfSeed,
388 				   4, counter,
389 				   0, NULL);
390 	    memcpy(mask + outLen, &digest.digest, digestSize);
391 	    outLen += digestSize;
392 	}
393 	/* if the mask is not modulo TPM_DIGEST_SIZE, only part of the final digest is needed */
394 	else {
395 	    /* hash to a temporary digest variable */
396 	    rc = TSS_Hash_Generate(&digest,
397 				   mgfSeedlen, mgfSeed,
398 				   4, counter,
399 				   0, NULL);
400 	    /* copy what's needed */
401 	    memcpy(mask + outLen, &digest.digest, maskLen - outLen);
402 	    outLen = maskLen;           /* outLen = outLen + maskLen - outLen */
403 	}
404     }
405     /* 4.Output the leading l octets of T as the octet string mask. */
406     return rc;
407 }
408 
409 /*
410   OAEP Padding
411 */
412 
413 /* TSS_RSA_padding_add_PKCS1_OAEP() is a variation of the the openSSL function
414 
415    int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
416    unsigned char *f, int fl, unsigned char *p, int pl);
417 
418    It is used because the openssl function is hard coded to SHA1.
419 
420    This function was independently written from the PKCS1 specification "9.1.1.1 Encoding
421    Operation" and PKCS#1 v2.2, intended to be unencumbered by any license.
422 
423 
424    | <-			  emLen					   -> |
425 
426                          |  lHash |    PS     | 01 |  Message	      |
427 
428                             SHA                       flen
429 
430                          |  db                                        |
431 			 |  dbMask                                    |
432         |  seed          |
433 
434 	   SHA
435 
436         |  seedMask      |
437    | 00 |  maskSeed      |   maskedDB                                 |
438 */
439 
TSS_RSA_padding_add_PKCS1_OAEP(unsigned char * em,uint32_t emLen,const unsigned char * from,uint32_t fLen,const unsigned char * p,int plen,TPMI_ALG_HASH halg)440 TPM_RC TSS_RSA_padding_add_PKCS1_OAEP(unsigned char *em, uint32_t emLen,
441 				      const unsigned char *from, uint32_t fLen,
442 				      const unsigned char *p,
443 				      int plen,
444 				      TPMI_ALG_HASH halg)
445 {
446     TPM_RC		rc = 0;
447     TPMT_HA 		lHash;
448     unsigned char 	*db = NULL;		/* compiler false positive */
449 
450     unsigned char *dbMask = NULL;			/* freed @1 */
451     unsigned char *seed = NULL;				/* freed @2 */
452     unsigned char *maskedDb;
453     unsigned char *seedMask = NULL;		/* compiler false positive */
454     unsigned char *maskedSeed;
455 
456     uint16_t hlen = TSS_GetDigestSize(halg);
457 
458     /* 1.a. If the length of L is greater than the input limitation for */
459     /* the hash function (2^61-1 octets for SHA-1) then output "parameter */
460     /* string too long" and stop. */
461     if (rc == 0) {
462 	if (plen > 0xffff) {
463 	    if (tssVerbose) printf("TSS_RSA_padding_add_PKCS1_OAEP: Error, "
464 				   "label %u too long\n", plen);
465 	    rc = TSS_RC_RSA_PADDING;
466 	}
467     }
468     /* 1.b. If ||M|| > emLen-2hLen-1 then output "message too long" and stop. */
469     if (rc == 0) {
470 	if (emLen < ((2 * hlen) + 2 + fLen)) {
471 	    if (tssVerbose) printf("TSS_RSA_padding_add_PKCS1_OAEP: Error, "
472 				   "message length %u too large for encoded length %u\n",
473 				   fLen, emLen);
474 	    rc = TSS_RC_RSA_PADDING;
475 	}
476     }
477     /* 2.a. Let lHash = Hash(L), an octet string of length hLen. */
478     if (rc == 0) {
479 	lHash.hashAlg = halg;
480 	rc = TSS_Hash_Generate(&lHash,
481 			       plen, p,
482 			       0, NULL);
483     }
484     if (rc == 0) {
485 	/* 2.b. Generate an octet string PS consisting of emLen-||M||-2hLen-2 zero octets. The
486 	   length of PS may be 0. */
487 	/* 2.c. Concatenate lHash, PS, a single octet of 0x01 the message M, to form a data block DB
488 	   as: DB = lHash || PS || 01 || M */
489 	/* NOTE Since db is eventually maskedDb, part of em, create directly in em */
490 	db = em + hlen + 1;
491 	memcpy(db, &lHash.digest, hlen);			/* lHash */
492 	/* PSlen = emlen - flen - (2 * hlen) - 2 */
493 	memset(db + hlen, 0,					/* PS */
494 	       emLen - fLen - (2 * hlen) - 2);
495 	/* position of 0x01 in db is
496 	   hlen + PSlen =
497 	   hlen + emlen - flen - (2 * hlen) - 2 =
498 	   emlen - hlen - flen - 2 */
499 	db[emLen - fLen - hlen - 2] = 0x01;
500 	memcpy(db + emLen - fLen - hlen - 1, from, fLen);	/* M */
501     }
502     /* 2.d. Generate a random octet string seed of length hLen. */
503     if (rc == 0) {
504 	rc = TSS_Malloc(&seed, hlen);
505     }
506     if (rc == 0) {
507 	rc = TSS_RandBytes(seed, hlen);
508     }
509     if (rc == 0) {
510 	rc = TSS_Malloc(&dbMask, emLen - hlen - 1);
511     }
512     if (rc == 0) {
513 	/* 2.e. Let dbMask = MGF(seed, emLen-hLen-1). */
514 	rc = TSS_MGF1(dbMask, emLen - hlen -1,	/* dbLen */
515 		      seed, hlen,
516 		      halg);
517     }
518     if (rc == 0) {
519 	/* 2.f. Let maskedDB = DB xor dbMask. */
520 	/* NOTE Since maskedDB is eventually em, XOR directly to em */
521 	maskedDb = em + hlen + 1;
522 	TSS_XOR(maskedDb, db, dbMask, emLen - hlen -1);
523 	/* 2.g. Let seedMask = MGF(maskedDB, hLen). */
524 	/* NOTE Since seedMask is eventually em, create directly to em */
525 	seedMask = em + 1;
526 	rc = TSS_MGF1(seedMask, hlen,
527 		      maskedDb, emLen - hlen - 1,
528 		      halg);
529     }
530     if (rc == 0) {
531 	/* 2.h. Let maskedSeed = seed xor seedMask. */
532 	/* NOTE Since maskedSeed is eventually em, create directly to em */
533 	maskedSeed = em + 1;
534 	TSS_XOR(maskedSeed, seed, seedMask, hlen);
535 	/* 2.i. 0x00, maskedSeed, and maskedDb to form EM */
536 	/* NOTE Created directly in em */
537     }
538     free(dbMask);		/* @1 */
539     free(seed);			/* @2 */
540     return rc;
541 }
542 
543 /* TPM_XOR XOR's 'in1' and 'in2' of 'length', putting the result in 'out'
544 
545  */
546 
TSS_XOR(unsigned char * out,const unsigned char * in1,const unsigned char * in2,size_t length)547 void TSS_XOR(unsigned char *out,
548 	     const unsigned char *in1,
549 	     const unsigned char *in2,
550 	     size_t length)
551 {
552     size_t i;
553 
554     for (i = 0 ; i < length ; i++) {
555 	out[i] = in1[i] ^ in2[i];
556     }
557     return;
558 }
559 
560 /*
561   AES
562 */
563 
564 #define TSS_AES_KEY_BITS 128
565 
566 /* TSS_Sym_GetBlockSize() returns the block size for the symmetric algorithm.  Returns 0 on for an
567    unknown algorithm.
568 */
569 
570 /* NOTE: Marked as const function in header */
571 
TSS_Sym_GetBlockSize(TPM_ALG_ID symmetricAlg,uint16_t keySizeInBits)572 uint16_t TSS_Sym_GetBlockSize(TPM_ALG_ID	symmetricAlg,
573 			      uint16_t		keySizeInBits)
574 {
575     keySizeInBits = keySizeInBits;
576 
577     switch (symmetricAlg) {
578 #ifdef TPM_ALG_AES
579       case TPM_ALG_AES:
580 #endif
581 #ifdef TPM_ALG_SM4 /* Both AES and SM4 use the same block size */
582       case TPM_ALG_SM4:
583 #endif
584 	return  16;
585       default:
586 	return 0;
587     }
588     return 0;
589 }
590 
591