237 |
return dwReturn; |
return dwReturn; |
238 |
} |
} |
239 |
|
|
240 |
DWORD BuildPrivateKeyTlv(__in PCARD_DATA pCardData, __in PRSAPUBLICKEYBLOB pbPublicKeyBlob, |
DWORD BuildSingleTlv(__in PBYTE buffer, __in BYTE bTlv, __in DWORD dwTlvSize, __inout PDWORD pdwOffset) |
241 |
|
{ |
242 |
|
DWORD dwSize = 1; |
243 |
|
buffer[(*pdwOffset)++] = bTlv; |
244 |
|
// truncate if too long |
245 |
|
if (dwTlvSize > 0xFFFF) dwTlvSize = 0xFFFF; |
246 |
|
if (dwTlvSize < 0x7F) |
247 |
|
{ |
248 |
|
buffer[(*pdwOffset)++] = (BYTE) dwTlvSize; |
249 |
|
dwSize++; |
250 |
|
} |
251 |
|
else if (dwTlvSize < 0xFF) |
252 |
|
{ |
253 |
|
buffer[(*pdwOffset)++] = 0x81; |
254 |
|
buffer[(*pdwOffset)++] = (BYTE) dwTlvSize; |
255 |
|
dwSize+=2; |
256 |
|
} |
257 |
|
else |
258 |
|
{ |
259 |
|
buffer[(*pdwOffset)++] = 0x82; |
260 |
|
buffer[(*pdwOffset)++] = (BYTE) (dwTlvSize / 0x100); |
261 |
|
buffer[(*pdwOffset)++] = (BYTE) (dwTlvSize % 0x100); |
262 |
|
dwSize+=3; |
263 |
|
} |
264 |
|
return dwSize; |
265 |
|
} |
266 |
|
|
267 |
|
DWORD BuildPrivateKeyTlv(__in PCARD_DATA pCardData, __in PRSAPUBLICKEYBLOB pbPublicKeyBlob, |
268 |
|
__in OPENPGP_CONTAINER dwContainer, __in BYTE bFormat, |
269 |
__out PBYTE * ppbTlv, __out PDWORD pdwTlvSize) |
__out PBYTE * ppbTlv, __out PDWORD pdwTlvSize) |
270 |
{ |
{ |
271 |
DWORD dwReturn; |
// structure of the keyblob |
272 |
|
//BLOBHEADER blobheader; |
273 |
|
//RSAPUBKEY rsapubkey; |
274 |
|
//BYTE modulus[rsapubkey.bitlen/8]; |
275 |
|
//BYTE prime1[rsapubkey.bitlen/16]; |
276 |
|
//BYTE prime2[rsapubkey.bitlen/16]; |
277 |
|
//BYTE exponent1[rsapubkey.bitlen/16]; |
278 |
|
//BYTE exponent2[rsapubkey.bitlen/16]; |
279 |
|
//BYTE coefficient[rsapubkey.bitlen/16]; |
280 |
|
//BYTE privateExponent[rsapubkey.bitlen/8]; |
281 |
|
DWORD dwReturn = 0; |
282 |
|
|
283 |
|
DWORD bitlen = pbPublicKeyBlob->rsapubkey.bitlen; |
284 |
|
PBYTE pbPublicKeyData = (PBYTE) pbPublicKeyBlob + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY); |
285 |
|
// 7F48 len is < 7F so its encoded len is 1 bytes |
286 |
|
// 3 bytes max + length * 7 potential plv |
287 |
|
BYTE b7F48Header[(3 +1) * 7 + 3] = {0x7F, 0x48}; |
288 |
|
BYTE b5F48Header[3 + 2] = {0x5F, 0x48}; |
289 |
|
BYTE b4DHeader[3 + 1] = {0x4D}; |
290 |
|
DWORD dwOffset = 0; |
291 |
|
DWORD dw7F48HeaderSize, dw5F48HeaderSize, dw4DHeaderSize; |
292 |
|
DWORD dwKeyDataSize, dwExtendedHeaderListSize; |
293 |
__try |
__try |
294 |
{ |
{ |
295 |
|
// build the 7F48 header + the data into a buffer |
296 |
|
dwOffset = 3; |
297 |
|
dw7F48HeaderSize = 0; |
298 |
|
dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x91, sizeof(DWORD), &dwOffset); |
299 |
|
dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x92, bitlen / 16, &dwOffset); |
300 |
|
dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x93, bitlen / 16, &dwOffset); |
301 |
|
if (bFormat & 2) |
302 |
|
{ |
303 |
|
// add crt (chineese reminder theorem) template |
304 |
|
dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x94, bitlen / 16, &dwOffset); |
305 |
|
dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x95, bitlen / 16, &dwOffset); |
306 |
|
dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x96, bitlen / 16, &dwOffset); |
307 |
|
} |
308 |
|
if (bFormat & 1) |
309 |
|
{ |
310 |
|
dw7F48HeaderSize += BuildSingleTlv(b7F48Header, 0x97, bitlen / 8, &dwOffset); |
311 |
|
} |
312 |
|
b7F48Header[2] = (BYTE) dw7F48HeaderSize; |
313 |
|
dw7F48HeaderSize += 3; // before = only content, after += header size |
314 |
|
// build 5F48 header in a buffer |
315 |
|
// size of the data |
316 |
|
dwKeyDataSize = sizeof(DWORD) // e |
317 |
|
+ bitlen / 16 //prime1 |
318 |
|
+ bitlen / 16 //prime2 |
319 |
|
; |
320 |
|
if (bFormat & 2) |
321 |
|
{ |
322 |
|
dwKeyDataSize+= bitlen / 16 //coefficient |
323 |
|
+ bitlen / 16 //exp1 |
324 |
|
+ bitlen / 16 //exp2 |
325 |
|
; |
326 |
|
} |
327 |
|
if (bFormat & 1) |
328 |
|
{ |
329 |
|
dwKeyDataSize+= bitlen / 8 ; //modulus |
330 |
|
} |
331 |
|
dwOffset = 1; |
332 |
|
dw5F48HeaderSize = 1 + BuildSingleTlv(b5F48Header, 0x48, dwKeyDataSize, &dwOffset); |
333 |
|
// build the extended header list in a buffer |
334 |
|
dwExtendedHeaderListSize = 2 // for the crt to indicate the private key |
335 |
|
+ dw7F48HeaderSize |
336 |
|
+ dw5F48HeaderSize |
337 |
|
+ dwKeyDataSize; |
338 |
|
dwOffset = 0; |
339 |
|
dw4DHeaderSize = BuildSingleTlv(b4DHeader, 0x4D, dwExtendedHeaderListSize, &dwOffset); |
340 |
|
|
341 |
|
// allocate the memory |
342 |
|
*pdwTlvSize = dw4DHeaderSize + dwExtendedHeaderListSize; |
343 |
|
*ppbTlv = pCardData->pfnCspAlloc(*pdwTlvSize); |
344 |
|
if (! *ppbTlv) |
345 |
|
{ |
346 |
|
dwReturn = SCARD_E_NO_MEMORY; |
347 |
|
__leave; |
348 |
|
} |
349 |
|
// 4D header |
350 |
|
dwOffset = 0; |
351 |
|
memcpy(*ppbTlv + dwOffset, b4DHeader, dw4DHeaderSize); |
352 |
|
dwOffset += dw4DHeaderSize; |
353 |
|
// control reference templace |
354 |
|
(*ppbTlv)[dwOffset++] = Containers[dwContainer].Tag; |
355 |
|
(*ppbTlv)[dwOffset++] = 0; |
356 |
|
// cardholder private key template |
357 |
|
memcpy(*ppbTlv + dwOffset, b7F48Header, dw7F48HeaderSize); |
358 |
|
dwOffset += dw7F48HeaderSize; |
359 |
|
// Concatenation of key data header |
360 |
|
memcpy(*ppbTlv + dwOffset, b5F48Header, dw5F48HeaderSize); |
361 |
|
dwOffset += dw5F48HeaderSize; |
362 |
|
// Concatenation of key data |
363 |
|
// exponent in little endian |
364 |
|
(*ppbTlv)[dwOffset++] = (BYTE) (pbPublicKeyBlob->rsapubkey.pubexp / 0x1000000); |
365 |
|
(*ppbTlv)[dwOffset++] = (BYTE) ((pbPublicKeyBlob->rsapubkey.pubexp % 0x1000000) / 0x10000); |
366 |
|
(*ppbTlv)[dwOffset++] = (BYTE) ((pbPublicKeyBlob->rsapubkey.pubexp % 0x10000) / 0x100); |
367 |
|
(*ppbTlv)[dwOffset++] = (BYTE) ((pbPublicKeyBlob->rsapubkey.pubexp % 0x100) / 0x1); |
368 |
|
// prime1 |
369 |
|
memcpy(*ppbTlv + dwOffset, pbPublicKeyData + bitlen/8 , bitlen / 16); |
370 |
|
dwOffset += bitlen / 16; |
371 |
|
// prime2 |
372 |
|
memcpy(*ppbTlv + dwOffset, pbPublicKeyData + (2+1) * bitlen / 16 , bitlen / 16); |
373 |
|
dwOffset += bitlen / 16; |
374 |
|
if (bFormat & 2) |
375 |
|
{ |
376 |
|
// coeff |
377 |
|
memcpy(*ppbTlv + dwOffset, pbPublicKeyData + (2+1 + 3) * bitlen / 16 , bitlen / 16); |
378 |
|
dwOffset += bitlen / 16; |
379 |
|
// exponent1 |
380 |
|
memcpy(*ppbTlv + dwOffset, pbPublicKeyData + (2+1 + 1) * bitlen / 16 , bitlen / 16); |
381 |
|
dwOffset += bitlen / 16; |
382 |
|
// exponent2 |
383 |
|
memcpy(*ppbTlv + dwOffset, pbPublicKeyData + (2+1 + 2) * bitlen / 16 , bitlen / 16); |
384 |
|
dwOffset += bitlen / 16; |
385 |
|
} |
386 |
|
if (bFormat & 1) |
387 |
|
{ |
388 |
|
// modulus |
389 |
|
memcpy(*ppbTlv + dwOffset, pbPublicKeyData, bitlen / 8); |
390 |
|
} |
391 |
} |
} |
392 |
__finally |
__finally |
393 |
{ |
{ |
566 |
{ |
{ |
567 |
DWORD dwReturn; |
DWORD dwReturn; |
568 |
PSTR szAlgorithmAttributes = NULL; |
PSTR szAlgorithmAttributes = NULL; |
569 |
PBYTE pbData = NULL; |
PBYTE pbTlv = NULL; |
570 |
DWORD dwResponseSize; |
DWORD dwTlvSize; |
571 |
|
PBYTE pbCommand = NULL; |
572 |
|
DWORD dwCommandSize; |
573 |
OPENPGP_ALGORITHM_ATTRIBUTE Attributes; |
OPENPGP_ALGORITHM_ATTRIBUTE Attributes; |
574 |
PRSAPUBLICKEYBLOB pbPublicKeyBlob = (PRSAPUBLICKEYBLOB) pBlob; |
PRSAPUBLICKEYBLOB pbPublicKeyBlob = (PRSAPUBLICKEYBLOB) pBlob; |
575 |
|
BYTE bCommand[] = {0x00,0xDB,0x3F,0xFF}; |
576 |
__try |
__try |
577 |
{ |
{ |
578 |
Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer); |
Trace(WINEVENT_LEVEL_VERBOSE, L"Enter dwContainer=%d",dwContainer); |
579 |
// check blob |
// check blob |
580 |
if (pbPublicKeyBlob->blobheader.aiKeyAlg != Containers[dwContainer].aiKeyAlg) |
if (pbPublicKeyBlob->blobheader.aiKeyAlg != CALG_RSA_SIGN && |
581 |
|
pbPublicKeyBlob->blobheader.aiKeyAlg != CALG_RSA_KEYX) |
582 |
{ |
{ |
583 |
Trace(WINEVENT_LEVEL_ERROR, L"Wrong aiKeyAlg %d", pbPublicKeyBlob->blobheader.aiKeyAlg); |
Trace(WINEVENT_LEVEL_ERROR, L"Wrong aiKeyAlg %d", pbPublicKeyBlob->blobheader.aiKeyAlg); |
584 |
dwReturn = SCARD_E_INVALID_PARAMETER; |
dwReturn = SCARD_E_INVALID_PARAMETER; |
585 |
__leave; |
__leave; |
586 |
} |
} |
587 |
if (pbPublicKeyBlob->blobheader.bType != PUBLICKEYBLOB) |
if (pbPublicKeyBlob->blobheader.bType != PRIVATEKEYBLOB) |
588 |
{ |
{ |
589 |
Trace(WINEVENT_LEVEL_ERROR, L"Wrong bType %d", pbPublicKeyBlob->blobheader.bType); |
Trace(WINEVENT_LEVEL_ERROR, L"Wrong bType %d", pbPublicKeyBlob->blobheader.bType); |
590 |
dwReturn = SCARD_E_INVALID_PARAMETER; |
dwReturn = SCARD_E_INVALID_PARAMETER; |
614 |
{ |
{ |
615 |
__leave; |
__leave; |
616 |
} |
} |
617 |
|
dwReturn = BuildPrivateKeyTlv(pCardData, pbPublicKeyBlob, dwContainer, Attributes.bFormat, &pbTlv, &dwTlvSize); |
618 |
|
if (dwReturn) |
619 |
|
{ |
620 |
|
__leave; |
621 |
|
} |
622 |
|
//TraceDump(WINEVENT_LEVEL_VERBOSE, pbTlv, dwTlvSize); |
623 |
|
if (dwTlvSize > 0xFF) |
624 |
|
{ |
625 |
|
dwCommandSize = 7 + dwTlvSize; |
626 |
|
|
627 |
|
} |
628 |
|
else |
629 |
|
{ |
630 |
|
dwCommandSize = 5 + dwTlvSize; |
631 |
|
} |
632 |
|
pbCommand = pCardData->pfnCspAlloc(dwCommandSize); |
633 |
|
if (!pbCommand) |
634 |
|
{ |
635 |
|
Trace(WINEVENT_LEVEL_ERROR, L"SCARD_E_NO_MEMORY"); |
636 |
|
dwReturn = SCARD_E_NO_MEMORY; |
637 |
|
__leave; |
638 |
|
} |
639 |
|
memcpy(pbCommand, bCommand, 4); |
640 |
|
if (dwTlvSize > 0xFF) |
641 |
|
{ |
642 |
|
pbCommand[4] = 0; |
643 |
|
pbCommand[5] = (BYTE)(dwTlvSize / 0x100); |
644 |
|
pbCommand[6] = (BYTE)(dwTlvSize % 0x100); |
645 |
|
memcpy(pbCommand + 7, pbTlv, dwTlvSize); |
646 |
|
} |
647 |
|
else |
648 |
|
{ |
649 |
|
pbCommand[4] = (BYTE) dwTlvSize; |
650 |
|
memcpy(pbCommand + 5, pbTlv, dwTlvSize); |
651 |
|
} |
652 |
|
dwReturn = SCardSendCommand(pCardData, pbCommand, dwCommandSize); |
653 |
|
if (dwReturn) |
654 |
|
{ |
655 |
|
__leave; |
656 |
|
} |
657 |
} |
} |
658 |
__finally |
__finally |
659 |
{ |
{ |
660 |
if (dwReturn) |
if (pbCommand) |
661 |
{ |
{ |
662 |
|
SecureZeroMemory(pbCommand, dwCommandSize); |
663 |
|
pCardData->pfnCspFree(pbCommand); |
664 |
|
} |
665 |
|
if (pbTlv) |
666 |
|
{ |
667 |
|
SecureZeroMemory(pbTlv, dwTlvSize); |
668 |
|
pCardData->pfnCspFree(pbTlv); |
669 |
} |
} |
670 |
} |
} |
671 |
return dwReturn; |
return dwReturn; |