Leaked source code of windows server 2003
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.

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