summaryrefslogtreecommitdiffstats
path: root/net/base/keygen_handler_win.cc
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-06 21:50:15 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-06 21:50:15 +0000
commit328abdba888397ce1da982f15a0083306a5be9d8 (patch)
treed1483154af9028242c2b5d2731c7c21df9170bf4 /net/base/keygen_handler_win.cc
parentef005e0346f65ab433306888a83278f08dfebc42 (diff)
downloadchromium_src-328abdba888397ce1da982f15a0083306a5be9d8.zip
chromium_src-328abdba888397ce1da982f15a0083306a5be9d8.tar.gz
chromium_src-328abdba888397ce1da982f15a0083306a5be9d8.tar.bz2
Simplify the Windows <keygen> implementation by making
better use of CryptoAPI. Contributed by Ryan Sleevi <ryan.sleevi@gmail.com>. Original review URL: http://codereview.chromium.org/1934001 R=wtc BUG=148 TEST=Keygenhandler.SmokeTest Review URL: http://codereview.chromium.org/2021003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46630 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/keygen_handler_win.cc')
-rw-r--r--net/base/keygen_handler_win.cc154
1 files changed, 49 insertions, 105 deletions
diff --git a/net/base/keygen_handler_win.cc b/net/base/keygen_handler_win.cc
index d6e5402..42997b6 100644
--- a/net/base/keygen_handler_win.cc
+++ b/net/base/keygen_handler_win.cc
@@ -18,42 +18,11 @@
#include "base/basictypes.h"
#include "base/logging.h"
#include "base/string_piece.h"
+#include "base/string_util.h"
#include "base/utf_string_conversions.h"
namespace net {
-// TODO(rsleevi): The following encoding functions are adapted from
-// base/crypto/rsa_private_key.h and can/should probably be refactored.
-static const uint8 kSequenceTag = 0x30;
-
-void PrependLength(size_t size, std::list<BYTE>* data) {
- // The high bit is used to indicate whether additional octets are needed to
- // represent the length.
- if (size < 0x80) {
- data->push_front(static_cast<BYTE>(size));
- } else {
- uint8 num_bytes = 0;
- while (size > 0) {
- data->push_front(static_cast<BYTE>(size & 0xFF));
- size >>= 8;
- num_bytes++;
- }
- CHECK_LE(num_bytes, 4);
- data->push_front(0x80 | num_bytes);
- }
-}
-
-void PrependTypeHeaderAndLength(uint8 type, uint32 length,
- std::vector<BYTE>* output) {
- std::list<BYTE> type_and_length;
-
- PrependLength(length, &type_and_length);
- type_and_length.push_front(type);
-
- output->insert(output->begin(), type_and_length.begin(),
- type_and_length.end());
-}
-
bool EncodeAndAppendType(LPCSTR type, const void* to_encode,
std::vector<BYTE>* output) {
BOOL ok;
@@ -79,22 +48,9 @@ bool EncodeAndAppendType(LPCSTR type, const void* to_encode,
return true;
}
-// Appends a DER IA5String containing |challenge| to |output|.
-// Returns true if encoding was successful.
-bool EncodeChallenge(const std::string& challenge, std::vector<BYTE>* output) {
- CERT_NAME_VALUE challenge_nv;
- challenge_nv.dwValueType = CERT_RDN_IA5_STRING;
- challenge_nv.Value.pbData = const_cast<BYTE*>(
- reinterpret_cast<const BYTE*>(challenge.data()));
- challenge_nv.Value.cbData = challenge.size();
-
- return EncodeAndAppendType(X509_ANY_STRING, &challenge_nv, output);
-}
-
-// Appends a DER SubjectPublicKeyInfo structure for the signing key in |prov|
-// to |output|.
-// Returns true if encoding was successful.
-bool EncodeSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) {
+// Assigns the contents of a CERT_PUBLIC_KEY_INFO structure for the signing
+// key in |prov| to |output|. Returns true if encoding was successful.
+bool GetSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) {
BOOL ok;
DWORD size = 0;
@@ -107,9 +63,10 @@ bool EncodeSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) {
if (!ok)
return false;
- std::vector<BYTE> public_key_info(size);
+ output->resize(size);
+
PCERT_PUBLIC_KEY_INFO public_key_casted =
- reinterpret_cast<PCERT_PUBLIC_KEY_INFO>(&public_key_info[0]);
+ reinterpret_cast<PCERT_PUBLIC_KEY_INFO>(&(*output)[0]);
ok = CryptExportPublicKeyInfoEx(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING,
szOID_RSA_RSA, 0, NULL, public_key_casted,
&size);
@@ -117,84 +74,71 @@ bool EncodeSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) {
if (!ok)
return false;
- public_key_info.resize(size);
+ output->resize(size);
- return EncodeAndAppendType(X509_PUBLIC_KEY_INFO, &public_key_info[0],
- output);
+ return true;
}
-// Generates an ASN.1 DER representation of the PublicKeyAndChallenge structure
-// from the signing key of |prov| and the specified |challenge| and appends it
+// Appends a DER SubjectPublicKeyInfo structure for the signing key in |prov|
// to |output|.
-// True if the the encoding was successfully generated.
-bool GetPublicKeyAndChallenge(HCRYPTPROV prov, const std::string& challenge,
- std::vector<BYTE>* output) {
- if (!EncodeSubjectPublicKeyInfo(prov, output) ||
- !EncodeChallenge(challenge, output)) {
+// Returns true if encoding was successful.
+bool EncodeSubjectPublicKeyInfo(HCRYPTPROV prov, std::vector<BYTE>* output) {
+ std::vector<BYTE> public_key_info;
+ if (!GetSubjectPublicKeyInfo(prov, &public_key_info))
return false;
- }
- PrependTypeHeaderAndLength(kSequenceTag, output->size(), output);
- return true;
+ return EncodeAndAppendType(X509_PUBLIC_KEY_INFO, &public_key_info[0],
+ output);
}
// Generates a DER encoded SignedPublicKeyAndChallenge structure from the
-// signing key of |prov| and the specified |challenge| string and appends it
-// to |output|.
+// signing key of |prov| and the specified ASCII |challenge| string and
+// appends it to |output|.
// True if the encoding was successfully generated.
bool GetSignedPublicKeyAndChallenge(HCRYPTPROV prov,
const std::string& challenge,
std::string* output) {
- std::vector<BYTE> pkac;
- if (!GetPublicKeyAndChallenge(prov, challenge, &pkac))
+ std::wstring wide_challenge = ASCIIToWide(challenge);
+ std::vector<BYTE> spki;
+
+ if (!GetSubjectPublicKeyInfo(prov, &spki))
return false;
- std::vector<BYTE> signature;
- std::vector<BYTE> signed_pkac;
- DWORD size = 0;
- BOOL ok;
+ // PublicKeyAndChallenge ::= SEQUENCE {
+ // spki SubjectPublicKeyInfo,
+ // challenge IA5STRING
+ // }
+ CERT_KEYGEN_REQUEST_INFO pkac;
+ pkac.dwVersion = CERT_KEYGEN_REQUEST_V1;
+ pkac.SubjectPublicKeyInfo =
+ *reinterpret_cast<PCERT_PUBLIC_KEY_INFO>(&spki[0]);
+ pkac.pwszChallengeString = const_cast<wchar_t*>(wide_challenge.c_str());
- // While the MSDN documentation states that CERT_SIGNED_CONTENT_INFO should
- // be an X.509 certificate type, for encoding this is not necessary. The
- // result of encoding this structure will be a DER-encoded structure with
- // the ASN.1 equivalent of
- // ::= SEQUENCE {
- // ToBeSigned IMPLICIT OCTET STRING,
- // SignatureAlgorithm AlgorithmIdentifier,
- // Signature BIT STRING
- // }
- //
- // This happens to be the same naive type as an SPKAC, so this works.
- CERT_SIGNED_CONTENT_INFO info;
- info.ToBeSigned.cbData = pkac.size();
- info.ToBeSigned.pbData = &pkac[0];
- info.SignatureAlgorithm.pszObjId = szOID_RSA_MD5RSA;
- info.SignatureAlgorithm.Parameters.cbData = 0;
- info.SignatureAlgorithm.Parameters.pbData = NULL;
-
- ok = CryptSignCertificate(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING,
- info.ToBeSigned.pbData, info.ToBeSigned.cbData,
- &info.SignatureAlgorithm, NULL, NULL, &size);
+ CRYPT_ALGORITHM_IDENTIFIER sig_alg;
+ memset(&sig_alg, 0, sizeof(sig_alg));
+ sig_alg.pszObjId = szOID_RSA_MD5RSA;
+
+ BOOL ok;
+ DWORD size = 0;
+ std::vector<BYTE> signed_pkac;
+ ok = CryptSignAndEncodeCertificate(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING,
+ X509_KEYGEN_REQUEST_TO_BE_SIGNED,
+ &pkac, &sig_alg, NULL,
+ NULL, &size);
DCHECK(ok);
if (!ok)
return false;
- signature.resize(size);
- info.Signature.cbData = signature.size();
- info.Signature.pbData = &signature[0];
- info.Signature.cUnusedBits = 0;
-
- ok = CryptSignCertificate(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING,
- info.ToBeSigned.pbData, info.ToBeSigned.cbData,
- &info.SignatureAlgorithm, NULL,
- info.Signature.pbData, &info.Signature.cbData);
+ signed_pkac.resize(size);
+ ok = CryptSignAndEncodeCertificate(prov, AT_KEYEXCHANGE, X509_ASN_ENCODING,
+ X509_KEYGEN_REQUEST_TO_BE_SIGNED,
+ &pkac, &sig_alg, NULL,
+ &signed_pkac[0], &size);
DCHECK(ok);
- if (!ok || !EncodeAndAppendType(X509_CERT, &info, &signed_pkac))
+ if (!ok)
return false;
- output->assign(reinterpret_cast<char*>(&signed_pkac[0]),
- signed_pkac.size());
-
+ output->assign(reinterpret_cast<char*>(&signed_pkac[0]), size);
return true;
}