Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

580 lines
16 KiB

  1. //+-------------------------------------------------------------------------
  2. // Microsoft Windows
  3. //
  4. // Copyright (C) Microsoft Corporation, 2001 - 2001
  5. //
  6. // File: verhash.cpp
  7. //
  8. // Contents: Minimal Cryptographic functions to verify ASN.1 encoded
  9. // signed hashes. Signed hashes are used in X.509 certificates
  10. // and PKCS #7 signed data.
  11. //
  12. // Also contains md5 or sha1 memory hash function.
  13. //
  14. //
  15. // Functions: MinCryptDecodeHashAlgorithmIdentifier
  16. // MinCryptHashMemory
  17. // MinCryptVerifySignedHash
  18. //
  19. // History: 17-Jan-01 philh created
  20. //--------------------------------------------------------------------------
  21. #include "global.hxx"
  22. #include <md5.h>
  23. #include <md2.h>
  24. #include <sha.h>
  25. #include <rsa.h>
  26. #define MAX_RSA_PUB_KEY_BIT_LEN 4096
  27. #define MAX_RSA_PUB_KEY_BYTE_LEN (MAX_RSA_PUB_KEY_BIT_LEN / 8 )
  28. #define MAX_BSAFE_PUB_KEY_MODULUS_BYTE_LEN \
  29. (MAX_RSA_PUB_KEY_BYTE_LEN + sizeof(DWORD) * 4)
  30. typedef struct _BSAFE_PUB_KEY_CONTENT {
  31. BSAFE_PUB_KEY Header;
  32. BYTE rgbModulus[MAX_BSAFE_PUB_KEY_MODULUS_BYTE_LEN];
  33. } BSAFE_PUB_KEY_CONTENT, *PBSAFE_PUB_KEY_CONTENT;
  34. #ifndef RSA1
  35. #define RSA1 ((DWORD)'R'+((DWORD)'S'<<8)+((DWORD)'A'<<16)+((DWORD)'1'<<24))
  36. #endif
  37. // from \nt\ds\win32\ntcrypto\scp\nt_sign.c
  38. //
  39. // Reverse ASN.1 Encodings of possible hash identifiers. The leading byte is
  40. // the length of the remaining byte string.
  41. //
  42. static const BYTE
  43. *md2Encodings[]
  44. // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
  45. = { (CONST BYTE *)"\x12\x10\x04\x00\x05\x02\x02\x0d\xf7\x86\x48\x86\x2a\x08\x06\x0c\x30\x20\x30",
  46. (CONST BYTE *)"\x10\x10\x04\x02\x02\x0d\xf7\x86\x48\x86\x2a\x08\x06\x0a\x30\x1e\x30",
  47. (CONST BYTE *)"\x00" },
  48. *md5Encodings[]
  49. = { (CONST BYTE *)"\x12\x10\x04\x00\x05\x05\x02\x0d\xf7\x86\x48\x86\x2a\x08\x06\x0c\x30\x20\x30",
  50. (CONST BYTE *)"\x10\x10\x04\x05\x02\x0d\xf7\x86\x48\x86\x2a\x08\x06\x0a\x30\x1e\x30",
  51. (CONST BYTE *)"\x00" },
  52. *shaEncodings[]
  53. = { (CONST BYTE *)"\x0f\x14\x04\x00\x05\x1a\x02\x03\x0e\x2b\x05\x06\x09\x30\x21\x30",
  54. (CONST BYTE *)"\x0d\x14\x04\x1a\x02\x03\x0e\x2b\x05\x06\x07\x30\x1f\x30",
  55. (CONST BYTE *)"\x00"};
  56. typedef struct _ENCODED_OID_INFO {
  57. DWORD cbEncodedOID;
  58. const BYTE *pbEncodedOID;
  59. ALG_ID AlgId;
  60. } ENCODED_OID_INFO, *PENCODED_OID_INFO;
  61. //
  62. // SHA1/MD5/MD2 HASH OIDS
  63. //
  64. // #define szOID_OIWSEC_sha1 "1.3.14.3.2.26"
  65. const BYTE rgbOIWSEC_sha1[] =
  66. {0x2B, 0x0E, 0x03, 0x02, 0x1A};
  67. // #define szOID_OIWSEC_sha "1.3.14.3.2.18"
  68. const BYTE rgbOID_OIWSEC_sha[] =
  69. {0x2B, 0x0E, 0x03, 0x02, 0x12};
  70. // #define szOID_RSA_MD5 "1.2.840.113549.2.5"
  71. const BYTE rgbOID_RSA_MD5[] =
  72. {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05};
  73. // #define szOID_RSA_MD2 "1.2.840.113549.2.2"
  74. const BYTE rgbOID_RSA_MD2[] =
  75. {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02};
  76. //
  77. // RSA SHA1/MD5/MD2 SIGNATURE OIDS
  78. //
  79. // #define szOID_RSA_SHA1RSA "1.2.840.113549.1.1.5"
  80. const BYTE rgbOID_RSA_SHA1RSA[] =
  81. {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05};
  82. // #define szOID_RSA_MD5RSA "1.2.840.113549.1.1.4"
  83. const BYTE rgbOID_RSA_MD5RSA[] =
  84. {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04};
  85. // #define szOID_OIWSEC_sha1RSASign "1.3.14.3.2.29"
  86. const BYTE rgbOID_OIWSEC_sha1RSASign[] =
  87. {0x2B, 0x0E, 0x03, 0x02, 0x1D};
  88. // #define szOID_OIWSEC_shaRSA "1.3.14.3.2.15"
  89. const BYTE rgbOID_OIWSEC_shaRSA[] =
  90. {0x2B, 0x0E, 0x03, 0x02, 0x0F};
  91. // #define szOID_OIWSEC_md5RSA "1.3.14.3.2.3"
  92. const BYTE rgbOID_OIWSEC_md5RSA[] =
  93. {0x2B, 0x0E, 0x03, 0x02, 0x03};
  94. // #define szOID_RSA_MD2RSA "1.2.840.113549.1.1.2"
  95. const BYTE rgbOID_RSA_MD2RSA[] =
  96. {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x02};
  97. // #define szOID_OIWDIR_md2RSA "1.3.14.7.2.3.1"
  98. const BYTE rgbOID_OIWDIR_md2RSA[] =
  99. {0x2B, 0x0E, 0x07, 0x02, 0x03, 0x01};
  100. const ENCODED_OID_INFO HashAlgTable[] = {
  101. // Hash OIDs
  102. sizeof(rgbOIWSEC_sha1), rgbOIWSEC_sha1, CALG_SHA1,
  103. sizeof(rgbOID_OIWSEC_sha), rgbOID_OIWSEC_sha, CALG_SHA1,
  104. sizeof(rgbOID_RSA_MD5), rgbOID_RSA_MD5, CALG_MD5,
  105. sizeof(rgbOID_RSA_MD2), rgbOID_RSA_MD2, CALG_MD2,
  106. // Signature OIDs
  107. sizeof(rgbOID_RSA_SHA1RSA), rgbOID_RSA_SHA1RSA, CALG_SHA1,
  108. sizeof(rgbOID_RSA_MD5RSA), rgbOID_RSA_MD5RSA, CALG_MD5,
  109. sizeof(rgbOID_OIWSEC_sha1RSASign), rgbOID_OIWSEC_sha1RSASign, CALG_SHA1,
  110. sizeof(rgbOID_OIWSEC_shaRSA), rgbOID_OIWSEC_shaRSA, CALG_SHA1,
  111. sizeof(rgbOID_OIWSEC_md5RSA), rgbOID_OIWSEC_md5RSA, CALG_MD5,
  112. sizeof(rgbOID_RSA_MD2RSA), rgbOID_RSA_MD2RSA, CALG_MD2,
  113. sizeof(rgbOID_OIWDIR_md2RSA), rgbOID_OIWDIR_md2RSA, CALG_MD2,
  114. };
  115. #define HASH_ALG_CNT (sizeof(HashAlgTable) / sizeof(HashAlgTable[0]))
  116. //+-------------------------------------------------------------------------
  117. // Decodes an ASN.1 encoded Algorithm Identifier and converts to
  118. // a CAPI Hash AlgID, such as, CALG_SHA1 or CALG_MD5.
  119. //
  120. // Returns 0 if there isn't a CAPI AlgId corresponding to the Algorithm
  121. // Identifier.
  122. //
  123. // Only CALG_SHA1, CALG_MD5 and CALG_MD2 are supported.
  124. //--------------------------------------------------------------------------
  125. ALG_ID
  126. WINAPI
  127. MinCryptDecodeHashAlgorithmIdentifier(
  128. IN PCRYPT_DER_BLOB pAlgIdValueBlob
  129. )
  130. {
  131. ALG_ID HashAlgId = 0;
  132. LONG lSkipped;
  133. CRYPT_DER_BLOB rgAlgIdBlob[MINASN1_ALGID_BLOB_CNT];
  134. DWORD cbEncodedOID;
  135. const BYTE *pbEncodedOID;
  136. DWORD i;
  137. lSkipped = MinAsn1ParseAlgorithmIdentifier(
  138. pAlgIdValueBlob,
  139. rgAlgIdBlob
  140. );
  141. if (0 >= lSkipped)
  142. goto CommonReturn;
  143. cbEncodedOID = rgAlgIdBlob[MINASN1_ALGID_OID_IDX].cbData;
  144. pbEncodedOID = rgAlgIdBlob[MINASN1_ALGID_OID_IDX].pbData;
  145. for (i = 0; i < HASH_ALG_CNT; i++) {
  146. if (cbEncodedOID == HashAlgTable[i].cbEncodedOID &&
  147. 0 == memcmp(pbEncodedOID, HashAlgTable[i].pbEncodedOID,
  148. cbEncodedOID)) {
  149. HashAlgId = HashAlgTable[i].AlgId;
  150. break;
  151. }
  152. }
  153. CommonReturn:
  154. return HashAlgId;
  155. }
  156. #pragma warning (push)
  157. // local variable 'Md5Ctx' may be used without having been initialized
  158. #pragma warning (disable: 4701)
  159. //+-------------------------------------------------------------------------
  160. // Hashes one or more memory blobs according to the Hash ALG_ID.
  161. //
  162. // rgbHash is updated with the resultant hash. *pcbHash is updated with
  163. // the length associated with the hash algorithm.
  164. //
  165. // If the function succeeds, the return value is ERROR_SUCCESS. Otherwise,
  166. // a nonzero error code is returned.
  167. //
  168. // Only CALG_SHA1, CALG_MD5 and CALG_MD2 are supported.
  169. //--------------------------------------------------------------------------
  170. LONG
  171. WINAPI
  172. MinCryptHashMemory(
  173. IN ALG_ID HashAlgId,
  174. IN DWORD cBlob,
  175. IN PCRYPT_DER_BLOB rgBlob,
  176. OUT BYTE rgbHash[MINCRYPT_MAX_HASH_LEN],
  177. OUT DWORD *pcbHash
  178. )
  179. {
  180. A_SHA_CTX ShaCtx;
  181. MD5_CTX Md5Ctx;
  182. MD2_CTX Md2Ctx;
  183. DWORD iBlob;
  184. switch (HashAlgId) {
  185. case CALG_MD2:
  186. memset(&Md2Ctx, 0, sizeof(Md2Ctx));
  187. *pcbHash = MINCRYPT_MD2_HASH_LEN;
  188. break;
  189. case CALG_MD5:
  190. MD5Init(&Md5Ctx);
  191. *pcbHash = MINCRYPT_MD5_HASH_LEN;
  192. break;
  193. case CALG_SHA1:
  194. A_SHAInit(&ShaCtx);
  195. *pcbHash = MINCRYPT_SHA1_HASH_LEN;
  196. break;
  197. default:
  198. *pcbHash = 0;
  199. return NTE_BAD_ALGID;
  200. }
  201. for (iBlob = 0; iBlob < cBlob; iBlob++) {
  202. BYTE *pb = rgBlob[iBlob].pbData;
  203. DWORD cb = rgBlob[iBlob].cbData;
  204. if (0 == cb)
  205. continue;
  206. switch (HashAlgId) {
  207. case CALG_MD2:
  208. MD2Update(&Md2Ctx, pb, cb);
  209. break;
  210. case CALG_MD5:
  211. MD5Update(&Md5Ctx, pb, cb);
  212. break;
  213. case CALG_SHA1:
  214. A_SHAUpdate(&ShaCtx, pb, cb);
  215. break;
  216. }
  217. }
  218. switch (HashAlgId) {
  219. case CALG_MD2:
  220. MD2Final(&Md2Ctx);
  221. memcpy(rgbHash, Md2Ctx.state, MINCRYPT_MD2_HASH_LEN);
  222. break;
  223. case CALG_MD5:
  224. MD5Final(&Md5Ctx);
  225. assert(MD5DIGESTLEN == MINCRYPT_MD5_HASH_LEN);
  226. memcpy(rgbHash, Md5Ctx.digest, MD5DIGESTLEN);
  227. break;
  228. case CALG_SHA1:
  229. A_SHAFinal(&ShaCtx, rgbHash);
  230. break;
  231. }
  232. return ERROR_SUCCESS;
  233. }
  234. #pragma warning (pop)
  235. //+=========================================================================
  236. // MinCryptVerifySignedHash Support Functions
  237. //-=========================================================================
  238. VOID
  239. WINAPI
  240. I_ReverseAndCopyBytes(
  241. OUT BYTE *pbDst,
  242. IN const BYTE *pbSrc,
  243. IN DWORD cb
  244. )
  245. {
  246. if (0 == cb)
  247. return;
  248. for (pbDst += cb - 1; cb > 0; cb--)
  249. *pbDst-- = *pbSrc++;
  250. }
  251. // The basis for much of the code in this function can be found in
  252. // \nt\ds\win32\ntcrypto\scp\nt_key.c
  253. LONG
  254. WINAPI
  255. I_ConvertParsedRSAPubKeyToBSafePubKey(
  256. IN CRYPT_DER_BLOB rgRSAPubKeyBlob[MINASN1_RSA_PUBKEY_BLOB_CNT],
  257. OUT PBSAFE_PUB_KEY_CONTENT pBSafePubKeyContent
  258. )
  259. {
  260. LONG lErr;
  261. DWORD cbModulus;
  262. const BYTE *pbAsn1Modulus;
  263. DWORD cbExp;
  264. const BYTE *pbAsn1Exp;
  265. DWORD cbTmpLen;
  266. LPBSAFE_PUB_KEY pBSafePubKey;
  267. // Get the ASN.1 public key modulus (BIG ENDIAN). The modulus length
  268. // is the public key byte length.
  269. cbModulus = rgRSAPubKeyBlob[MINASN1_RSA_PUBKEY_MODULUS_IDX].cbData;
  270. pbAsn1Modulus = rgRSAPubKeyBlob[MINASN1_RSA_PUBKEY_MODULUS_IDX].pbData;
  271. // Strip off a leading 0 byte. Its there in the decoded ASN
  272. // integer for an unsigned integer with the leading bit set.
  273. if (cbModulus > 1 && *pbAsn1Modulus == 0) {
  274. pbAsn1Modulus++;
  275. cbModulus--;
  276. }
  277. if (MAX_RSA_PUB_KEY_BYTE_LEN < cbModulus)
  278. goto ExceededMaxPubKeyModulusLen;
  279. // Get the ASN.1 public exponent (BIG ENDIAN).
  280. cbExp = rgRSAPubKeyBlob[MINASN1_RSA_PUBKEY_EXPONENT_IDX].cbData;
  281. pbAsn1Exp = rgRSAPubKeyBlob[MINASN1_RSA_PUBKEY_EXPONENT_IDX].pbData;
  282. // Strip off a leading 0 byte. Its there in the decoded ASN
  283. // integer for an unsigned integer with the leading bit set.
  284. if (cbExp > 1 && *pbAsn1Exp == 0) {
  285. pbAsn1Exp++;
  286. cbExp--;
  287. }
  288. if (sizeof(DWORD) < cbExp)
  289. goto ExceededMaxPubKeyExpLen;
  290. if (0 == cbModulus || 0 == cbExp)
  291. goto InvalidPubKey;
  292. // Update the BSAFE data structure from the parsed and length validated
  293. // ASN.1 public key modulus and exponent components.
  294. cbTmpLen = (sizeof(DWORD) * 2) - (cbModulus % (sizeof(DWORD) * 2));
  295. if ((sizeof(DWORD) * 2) != cbTmpLen)
  296. cbTmpLen += sizeof(DWORD) * 2;
  297. memset(pBSafePubKeyContent, 0, sizeof(*pBSafePubKeyContent));
  298. pBSafePubKey = &pBSafePubKeyContent->Header;
  299. pBSafePubKey->magic = RSA1;
  300. pBSafePubKey->keylen = cbModulus + cbTmpLen;
  301. pBSafePubKey->bitlen = cbModulus * 8;
  302. pBSafePubKey->datalen = cbModulus - 1;
  303. I_ReverseAndCopyBytes((BYTE *) &pBSafePubKey->pubexp, pbAsn1Exp, cbExp);
  304. I_ReverseAndCopyBytes(pBSafePubKeyContent->rgbModulus, pbAsn1Modulus,
  305. cbModulus);
  306. lErr = ERROR_SUCCESS;
  307. CommonReturn:
  308. return lErr;
  309. ExceededMaxPubKeyModulusLen:
  310. ExceededMaxPubKeyExpLen:
  311. InvalidPubKey:
  312. lErr = NTE_BAD_PUBLIC_KEY;
  313. goto CommonReturn;
  314. }
  315. // The basis for much of the code in this function can be found in
  316. // \nt\ds\win32\ntcrypto\scp\nt_sign.c
  317. LONG
  318. WINAPI
  319. I_VerifyPKCS1SigningFormat(
  320. IN BSAFE_PUB_KEY *pKey,
  321. IN ALG_ID HashAlgId,
  322. IN BYTE *pbHash,
  323. IN DWORD cbHash,
  324. IN BYTE *pbPKCS1Format
  325. )
  326. {
  327. LONG lErr = ERROR_INTERNAL_ERROR;
  328. const BYTE **rgEncOptions;
  329. BYTE rgbTmpHash[MINCRYPT_MAX_HASH_LEN];
  330. DWORD i;
  331. DWORD cb;
  332. BYTE *pbStart;
  333. DWORD cbTmp;
  334. switch (HashAlgId)
  335. {
  336. case CALG_MD2:
  337. rgEncOptions = md2Encodings;
  338. break;
  339. case CALG_MD5:
  340. rgEncOptions = md5Encodings;
  341. break;
  342. case CALG_SHA:
  343. rgEncOptions = shaEncodings;
  344. break;
  345. default:
  346. goto UnsupportedHash;
  347. }
  348. // Reverse the hash to match the signature.
  349. for (i = 0; i < cbHash; i++)
  350. rgbTmpHash[i] = pbHash[cbHash - (i + 1)];
  351. // See if it matches.
  352. if (0 != memcmp(rgbTmpHash, pbPKCS1Format, cbHash))
  353. {
  354. goto BadSignature;
  355. }
  356. cb = cbHash;
  357. for (i = 0; 0 != *rgEncOptions[i]; i += 1)
  358. {
  359. pbStart = (LPBYTE)rgEncOptions[i];
  360. cbTmp = *pbStart++;
  361. if (0 == memcmp(&pbPKCS1Format[cb], pbStart, cbTmp))
  362. {
  363. cb += cbTmp; // Adjust the end of the hash data.
  364. break;
  365. }
  366. }
  367. // check to make sure the rest of the PKCS #1 padding is correct
  368. if ((0x00 != pbPKCS1Format[cb])
  369. || (0x00 != pbPKCS1Format[pKey->datalen])
  370. || (0x1 != pbPKCS1Format[pKey->datalen - 1]))
  371. {
  372. goto BadSignature;
  373. }
  374. for (i = cb + 1; i < pKey->datalen - 1; i++)
  375. {
  376. if (0xff != pbPKCS1Format[i])
  377. {
  378. goto BadSignature;
  379. }
  380. }
  381. lErr = ERROR_SUCCESS;
  382. CommonReturn:
  383. return lErr;
  384. UnsupportedHash:
  385. lErr = NTE_BAD_ALGID;
  386. goto CommonReturn;
  387. BadSignature:
  388. lErr = NTE_BAD_SIGNATURE;
  389. goto CommonReturn;
  390. }
  391. //+-------------------------------------------------------------------------
  392. // Verifies a signed hash.
  393. //
  394. // The ASN.1 encoded Public Key Info is parsed and used to decrypt the
  395. // signed hash. The decrypted signed hash is compared with the input
  396. // hash.
  397. //
  398. // If the signed hash was successfully verified, ERROR_SUCCESS is returned.
  399. // Otherwise, a nonzero error code is returned.
  400. //
  401. // Only RSA signed hashes are supported.
  402. //
  403. // Only MD2, MD5 and SHA1 hashes are supported.
  404. //--------------------------------------------------------------------------
  405. LONG
  406. WINAPI
  407. MinCryptVerifySignedHash(
  408. IN ALG_ID HashAlgId,
  409. IN BYTE *pbHash,
  410. IN DWORD cbHash,
  411. IN PCRYPT_DER_BLOB pSignedHashContentBlob,
  412. IN PCRYPT_DER_BLOB pPubKeyInfoValueBlob
  413. )
  414. {
  415. LONG lErr;
  416. LONG lSkipped;
  417. CRYPT_DER_BLOB rgPubKeyInfoBlob[MINASN1_PUBKEY_INFO_BLOB_CNT];
  418. CRYPT_DER_BLOB rgRSAPubKeyBlob[MINASN1_RSA_PUBKEY_BLOB_CNT];
  419. BSAFE_PUB_KEY_CONTENT BSafePubKeyContent;
  420. LPBSAFE_PUB_KEY pBSafePubKey;
  421. DWORD cbSignature;
  422. const BYTE *pbAsn1Signature;
  423. BYTE rgbBSafeIn[MAX_BSAFE_PUB_KEY_MODULUS_BYTE_LEN];
  424. BYTE rgbBSafeOut[MAX_BSAFE_PUB_KEY_MODULUS_BYTE_LEN];
  425. // Attempt to parse and convert the ASN.1 encoded public key into
  426. // an RSA BSAFE formatted key.
  427. lSkipped = MinAsn1ParsePublicKeyInfo(
  428. pPubKeyInfoValueBlob,
  429. rgPubKeyInfoBlob
  430. );
  431. if (0 >= lSkipped)
  432. goto ParsePubKeyInfoError;
  433. lSkipped = MinAsn1ParseRSAPublicKey(
  434. &rgPubKeyInfoBlob[MINASN1_PUBKEY_INFO_PUBKEY_IDX],
  435. rgRSAPubKeyBlob
  436. );
  437. if (0 >= lSkipped)
  438. goto ParseRSAPubKeyError;
  439. lErr = I_ConvertParsedRSAPubKeyToBSafePubKey(
  440. rgRSAPubKeyBlob,
  441. &BSafePubKeyContent
  442. );
  443. if (ERROR_SUCCESS != lErr)
  444. goto CommonReturn;
  445. pBSafePubKey = &BSafePubKeyContent.Header;
  446. // Get the ASN.1 signature (BIG ENDIAN).
  447. //
  448. // It must be the same length as the public key
  449. cbSignature = pSignedHashContentBlob->cbData;
  450. pbAsn1Signature = pSignedHashContentBlob->pbData;
  451. if (cbSignature != pBSafePubKey->bitlen / 8)
  452. goto InvalidSignatureLen;
  453. // Decrypt the signature (LITTLE ENDIAN)
  454. assert(sizeof(rgbBSafeIn) >= cbSignature);
  455. I_ReverseAndCopyBytes(rgbBSafeIn, pbAsn1Signature, cbSignature);
  456. memset(&rgbBSafeIn[cbSignature], 0, sizeof(rgbBSafeIn) - cbSignature);
  457. memset(rgbBSafeOut, 0, sizeof(rgbBSafeOut));
  458. if (!BSafeEncPublic(pBSafePubKey, rgbBSafeIn, rgbBSafeOut))
  459. goto BSafeEncPublicError;
  460. lErr = I_VerifyPKCS1SigningFormat(
  461. pBSafePubKey,
  462. HashAlgId,
  463. pbHash,
  464. cbHash,
  465. rgbBSafeOut
  466. );
  467. CommonReturn:
  468. return lErr;
  469. ParsePubKeyInfoError:
  470. ParseRSAPubKeyError:
  471. lErr = NTE_BAD_PUBLIC_KEY;
  472. goto CommonReturn;
  473. InvalidSignatureLen:
  474. BSafeEncPublicError:
  475. lErr = NTE_BAD_SIGNATURE;
  476. goto CommonReturn;
  477. }