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.

323 lines
8.1 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: keys.c
  7. //
  8. // Contents: Well known keys for certificate validation
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 9-21-95 RichardW Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include "spbase.h"
  18. #include <oidenc.h>
  19. #include <rsa.h>
  20. #define SCHANNEL_GENKEY_NAME "SchannelGenKey"
  21. BOOL
  22. GenerateKeyPair(
  23. PSSL_CREDENTIAL_CERTIFICATE pCerts,
  24. PSTR pszDN,
  25. PSTR pszPassword,
  26. DWORD Bits)
  27. {
  28. BOOL fRet = FALSE;
  29. DWORD BitsCopy;
  30. DWORD dwPrivateSize;
  31. DWORD dwPublicSize;
  32. MD5_CTX md5Ctx;
  33. struct RC4_KEYSTRUCT rc4Key;
  34. BLOBHEADER *pCapiPrivate = NULL;
  35. BLOBHEADER *pCapiPublic = NULL;
  36. PRIVATE_KEY_FILE_ENCODE PrivateEncode;
  37. CERT_REQUEST_INFO Req;
  38. CRYPT_ALGORITHM_IDENTIFIER SignAlg;
  39. HCRYPTPROV hProv = 0;
  40. HCRYPTKEY hKey = 0;
  41. if(!SchannelInit(TRUE))
  42. {
  43. return FALSE;
  44. }
  45. pCerts->pPrivateKey = NULL;
  46. Req.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
  47. Req.Subject.pbData = NULL;
  48. pCerts->pCertificate = NULL;
  49. CryptAcquireContext(&hProv, SCHANNEL_GENKEY_NAME, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
  50. if(!CryptAcquireContext(&hProv, SCHANNEL_GENKEY_NAME, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))
  51. {
  52. goto error;
  53. }
  54. if(!CryptGenKey(hProv, CALG_RSA_SIGN, (Bits << 16) | CRYPT_EXPORTABLE, &hKey))
  55. {
  56. goto error;
  57. }
  58. if(!CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, NULL, &dwPrivateSize))
  59. {
  60. goto error;
  61. }
  62. pCapiPrivate = (BLOBHEADER *)SPExternalAlloc(dwPrivateSize);
  63. if(!CryptExportKey(hKey, 0, PRIVATEKEYBLOB, 0, (PBYTE)pCapiPrivate, &dwPrivateSize))
  64. {
  65. goto error;
  66. }
  67. if(!CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, NULL, &dwPublicSize))
  68. {
  69. goto error;
  70. }
  71. pCapiPublic = (BLOBHEADER *)SPExternalAlloc(dwPublicSize);
  72. if(!CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, (PBYTE)pCapiPublic, &dwPublicSize))
  73. {
  74. goto error;
  75. }
  76. // Encode the private key into a
  77. // priavate key blob.
  78. if(!CryptEncodeObject(X509_ASN_ENCODING,
  79. szPrivateKeyInfoEncode,
  80. pCapiPrivate,
  81. NULL,
  82. &PrivateEncode.EncryptedBlob.cbData))
  83. {
  84. goto error;
  85. }
  86. PrivateEncode.EncryptedBlob.pbData = SPExternalAlloc(PrivateEncode.EncryptedBlob.cbData);
  87. if(PrivateEncode.EncryptedBlob.pbData == NULL)
  88. {
  89. goto error;
  90. }
  91. if(!CryptEncodeObject(X509_ASN_ENCODING,
  92. szPrivateKeyInfoEncode,
  93. pCapiPrivate,
  94. PrivateEncode.EncryptedBlob.pbData,
  95. &PrivateEncode.EncryptedBlob.cbData))
  96. {
  97. goto error;
  98. }
  99. // Okay, now encrypt this
  100. MD5Init(&md5Ctx);
  101. MD5Update(&md5Ctx, pszPassword, lstrlen(pszPassword));
  102. MD5Final(&md5Ctx);
  103. rc4_key(&rc4Key, 16, md5Ctx.digest);
  104. ZeroMemory(&md5Ctx, sizeof(md5Ctx));
  105. rc4(&rc4Key,
  106. PrivateEncode.EncryptedBlob.cbData,
  107. PrivateEncode.EncryptedBlob.pbData);
  108. ZeroMemory(&rc4Key, sizeof(rc4Key));
  109. //
  110. PrivateEncode.Alg.pszObjId = szOID_RSA_ENCRYPT_RC4_MD5;
  111. PrivateEncode.Alg.Parameters.pbData = NULL;
  112. PrivateEncode.Alg.Parameters.cbData = 0;
  113. // Ah yes, now to encode them...
  114. //
  115. // First, the private key. Why? Well, it's at least straight-forward
  116. // First, get the size of the private key encode...
  117. if(!CryptEncodeObject(X509_ASN_ENCODING,
  118. szPrivateKeyFileEncode,
  119. &PrivateEncode,
  120. NULL,
  121. &pCerts->cbPrivateKey))
  122. {
  123. goto error;
  124. }
  125. pCerts->pPrivateKey = SPExternalAlloc(pCerts->cbPrivateKey);
  126. if(!CryptEncodeObject(X509_ASN_ENCODING,
  127. szPrivateKeyFileEncode,
  128. &PrivateEncode,
  129. pCerts->pPrivateKey,
  130. &pCerts->cbPrivateKey))
  131. {
  132. goto error;
  133. }
  134. SPExternalFree(PrivateEncode.EncryptedBlob.pbData);
  135. // Create the Req structure so we can encode it.
  136. Req.dwVersion = CERT_REQUEST_V1;
  137. // Initialize the PublicKeyInfo
  138. Req.SubjectPublicKeyInfo.Algorithm.pszObjId = szOID_RSA_RSA;
  139. Req.SubjectPublicKeyInfo.Algorithm.Parameters.cbData = 0;
  140. Req.SubjectPublicKeyInfo.Algorithm.Parameters.pbData = NULL;
  141. Req.SubjectPublicKeyInfo.PublicKey.cbData;
  142. // Encode the public key info
  143. if(!CryptEncodeObject(X509_ASN_ENCODING,
  144. szOID_RSA_RSA_Public,
  145. pCapiPublic,
  146. NULL,
  147. &Req.SubjectPublicKeyInfo.PublicKey.cbData))
  148. {
  149. goto error;
  150. }
  151. Req.SubjectPublicKeyInfo.PublicKey.pbData =
  152. SPExternalAlloc(Req.SubjectPublicKeyInfo.PublicKey.cbData);
  153. if(Req.SubjectPublicKeyInfo.PublicKey.pbData == NULL)
  154. {
  155. goto error;
  156. }
  157. // Encode the public key info
  158. if(!CryptEncodeObject(X509_ASN_ENCODING,
  159. szOID_RSA_RSA_Public,
  160. pCapiPublic,
  161. Req.SubjectPublicKeyInfo.PublicKey.pbData,
  162. &Req.SubjectPublicKeyInfo.PublicKey.cbData))
  163. {
  164. goto error;
  165. }
  166. Req.SubjectPublicKeyInfo.PublicKey.cUnusedBits = 0;
  167. // Encode the name
  168. Req.Subject.cbData = EncodeDN(NULL, pszDN, FALSE);
  169. if((LONG)Req.Subject.cbData < 0)
  170. {
  171. goto error;
  172. }
  173. Req.Subject.pbData = SPExternalAlloc(Req.Subject.cbData);
  174. if(Req.Subject.pbData== NULL)
  175. {
  176. goto error;
  177. }
  178. Req.Subject.cbData = EncodeDN(Req.Subject.pbData, pszDN, TRUE);
  179. if((LONG)Req.Subject.cbData < 0)
  180. {
  181. goto error;
  182. }
  183. // Attributes
  184. Req.cAttribute = 0;
  185. Req.rgAttribute = NULL;
  186. SignAlg.pszObjId = szOID_RSA_MD5RSA;
  187. SignAlg.Parameters.cbData = 0;
  188. SignAlg.Parameters.pbData = NULL;
  189. // Encode the public key info
  190. if(!CryptSignAndEncodeCertificate(
  191. hProv,
  192. AT_SIGNATURE,
  193. X509_ASN_ENCODING,
  194. X509_CERT_REQUEST_TO_BE_SIGNED,
  195. &Req,
  196. &SignAlg,
  197. NULL,
  198. NULL,
  199. &pCerts->cbCertificate))
  200. {
  201. goto error;
  202. }
  203. pCerts->pCertificate = SPExternalAlloc(pCerts->cbCertificate);
  204. if(pCerts->pCertificate == NULL)
  205. {
  206. goto error;
  207. }
  208. // Encode the public key info
  209. if(!CryptSignAndEncodeCertificate(
  210. hProv,
  211. AT_SIGNATURE,
  212. X509_ASN_ENCODING,
  213. X509_CERT_REQUEST_TO_BE_SIGNED,
  214. &Req,
  215. &SignAlg,
  216. NULL,
  217. pCerts->pCertificate,
  218. &pCerts->cbCertificate))
  219. {
  220. goto error;
  221. }
  222. fRet = TRUE;
  223. goto cleanup;
  224. error:
  225. if(pCerts->pPrivateKey)
  226. {
  227. SPExternalFree(pCerts->pPrivateKey);
  228. }
  229. if(pCerts->pCertificate)
  230. {
  231. SPExternalFree(pCerts->pCertificate);
  232. }
  233. cleanup:
  234. if(pCapiPrivate)
  235. {
  236. SPExternalFree(pCapiPrivate);
  237. }
  238. if(pCapiPublic)
  239. {
  240. SPExternalFree(pCapiPublic);
  241. }
  242. if(Req.SubjectPublicKeyInfo.PublicKey.pbData)
  243. {
  244. SPExternalFree(Req.SubjectPublicKeyInfo.PublicKey.pbData);
  245. }
  246. if(Req.Subject.pbData)
  247. {
  248. SPExternalFree(Req.Subject.pbData);
  249. }
  250. if(hKey != 0)
  251. {
  252. CryptDestroyKey(hKey);
  253. }
  254. if(hProv != 0)
  255. {
  256. CryptReleaseContext(hProv,0);
  257. CryptAcquireContext(&hProv, SCHANNEL_GENKEY_NAME, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET);
  258. }
  259. return(fRet);
  260. }