Skip to content

Commit ce8d7ef

Browse files
ItsMattLcopybara-github
authored andcommitted
Modify keyMetadata for provider detection.
* The cert() function returns certs/keys from the local store regardless of store.Prov. This creates a problem when a cert is in a different provider than store.Prov. * Add type-specific getProperty functions for str, int, & handle. Make getProperty generic. * Modify keyMetadata to lookup the key's individual provider based on property lookups. * Use the provider implementation property as the basis for determining software-backed keys. PiperOrigin-RevId: 407329444
1 parent 7d4f992 commit ce8d7ef

File tree

1 file changed

+70
-10
lines changed

1 file changed

+70
-10
lines changed

certtostore_windows.go

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ var (
113113
nCryptAlgorithmGroupProperty = wide("Algorithm Group") // NCRYPT_ALGORITHM_GROUP_PROPERTY
114114
nCryptUniqueNameProperty = wide("Unique Name") // NCRYPT_UNIQUE_NAME_PROPERTY
115115
nCryptECCCurveNameProperty = wide("ECCCurveName") // NCRYPT_ECC_CURVE_NAME_PROPERTY
116+
nCryptImplTypeProperty = wide("Impl Type") // NCRYPT_IMPL_TYPE_PROPERTY
117+
nCryptProviderHandleProperty = wide("Provider Handle") // NCRYPT_PROV_HANDLE
118+
119+
// Flags for NCRYPT_IMPL_TYPE_PROPERTY
120+
nCryptImplHardwareFlag = 0x00000001 // NCRYPT_IMPL_HARDWARE_FLAG
121+
nCryptImplSoftwareFlag = 0x00000002 // NCRYPT_IMPL_SOFTWARE_FLAG
122+
nCryptImplRemovableFlag = 0x00000008 // NCRYPT_IMPL_REMOVABLE_FLAG
123+
nCryptImplHardwareRngFlag = 0x00000010 // NCRYPT_IMPL_HARDWARE_RNG_FLAG
116124

117125
// curveIDs maps bcrypt key blob magic numbers to elliptic curves.
118126
curveIDs = map[uint32]elliptic.Curve{
@@ -413,15 +421,19 @@ func (w *WinCertStore) cert(issuers []string, searchRoot *uint16, store uint32)
413421
return cert, prev, nil
414422
}
415423

416-
// Close frees the handle to the certificate provider
417-
func (w *WinCertStore) Close() error {
418-
r, _, err := nCryptFreeObject.Call(w.Prov)
424+
func freeObject(h uintptr) error {
425+
r, _, err := nCryptFreeObject.Call(h)
419426
if r == 0 {
420427
return nil
421428
}
422429
return fmt.Errorf("NCryptFreeObject returned %X: %v", r, err)
423430
}
424431

432+
// Close frees the handle to the certificate provider
433+
func (w *WinCertStore) Close() error {
434+
return freeObject(w.Prov)
435+
}
436+
425437
// Link will associate the certificate installed in the system store to the user store.
426438
func (w *WinCertStore) Link() error {
427439
cert, _, err := w.cert(w.issuers, my, certStoreLocalMachine)
@@ -1066,21 +1078,39 @@ func (w *WinCertStore) generateRSA(keySize int) (crypto.Signer, error) {
10661078

10671079
func keyMetadata(kh uintptr, store *WinCertStore) (*Key, error) {
10681080
// uc is used to populate the unique container name attribute of the private key
1069-
uc, err := getProperty(kh, nCryptUniqueNameProperty)
1081+
uc, err := getPropertyStr(kh, nCryptUniqueNameProperty)
10701082
if err != nil {
10711083
return nil, fmt.Errorf("unable to determine key unique name: %v", err)
10721084
}
10731085

1086+
// get the provider handle
1087+
ph, err := getPropertyHandle(kh, nCryptProviderHandleProperty)
1088+
if err != nil {
1089+
return nil, fmt.Errorf("unable to determine key provider: %v", err)
1090+
}
1091+
defer freeObject(ph)
1092+
1093+
// get the provider implementation from the provider handle
1094+
impl, err := getPropertyInt(ph, nCryptImplTypeProperty)
1095+
if err != nil {
1096+
return nil, fmt.Errorf("unable to determine provider implementation: %v", err)
1097+
}
1098+
10741099
// Populate key storage locations for software backed keys.
10751100
var lc string
1076-
if store.ProvName != ProviderMSPlatform {
1101+
1102+
// Functions like cert() pull certs from the local store *regardless*
1103+
// of the provider OpenWinCertStore was given. This means we cannot rely on
1104+
// store.Prov to tell us which provider a given key resides in. Instead, we
1105+
// lookup the provider directly from the key properties.
1106+
if impl == nCryptImplSoftwareFlag {
10771107
uc, lc, err = softwareKeyContainers(uc)
10781108
if err != nil {
10791109
return nil, err
10801110
}
10811111
}
10821112

1083-
alg, err := getProperty(kh, nCryptAlgorithmGroupProperty)
1113+
alg, err := getPropertyStr(kh, nCryptAlgorithmGroupProperty)
10841114
if err != nil {
10851115
return nil, fmt.Errorf("unable to determine key algorithm: %v", err)
10861116
}
@@ -1109,7 +1139,7 @@ func keyMetadata(kh uintptr, store *WinCertStore) (*Key, error) {
11091139
return &Key{handle: kh, pub: pub, Container: uc, LegacyContainer: lc, AlgorithmGroup: alg}, nil
11101140
}
11111141

1112-
func getProperty(kh uintptr, property *uint16) (string, error) {
1142+
func getProperty(kh uintptr, property *uint16) ([]byte, error) {
11131143
var strSize uint32
11141144
r, _, err := nCryptGetProperty.Call(
11151145
kh,
@@ -1120,7 +1150,7 @@ func getProperty(kh uintptr, property *uint16) (string, error) {
11201150
0,
11211151
0)
11221152
if r != 0 {
1123-
return "", fmt.Errorf("NCryptGetProperty(%v) returned %X during size check: %v", property, r, err)
1153+
return nil, fmt.Errorf("NCryptGetProperty(%v) returned %X during size check: %v", property, r, err)
11241154
}
11251155

11261156
buf := make([]byte, strSize)
@@ -1133,9 +1163,39 @@ func getProperty(kh uintptr, property *uint16) (string, error) {
11331163
0,
11341164
0)
11351165
if r != 0 {
1136-
return "", fmt.Errorf("NCryptGetProperty %v returned %X during export: %v", property, r, err)
1166+
return nil, fmt.Errorf("NCryptGetProperty %v returned %X during export: %v", property, r, err)
11371167
}
11381168

1169+
return buf, nil
1170+
}
1171+
1172+
func getPropertyHandle(kh uintptr, property *uint16) (uintptr, error) {
1173+
buf, err := getProperty(kh, property)
1174+
if err != nil {
1175+
return 0, err
1176+
}
1177+
if len(buf) < 1 {
1178+
return 0, fmt.Errorf("empty result")
1179+
}
1180+
return **(**uintptr)(unsafe.Pointer(&buf)), nil
1181+
}
1182+
1183+
func getPropertyInt(kh uintptr, property *uint16) (int, error) {
1184+
buf, err := getProperty(kh, property)
1185+
if err != nil {
1186+
return 0, err
1187+
}
1188+
if len(buf) < 1 {
1189+
return 0, fmt.Errorf("empty result")
1190+
}
1191+
return **(**int)(unsafe.Pointer(&buf)), nil
1192+
}
1193+
1194+
func getPropertyStr(kh uintptr, property *uint16) (string, error) {
1195+
buf, err := getProperty(kh, property)
1196+
if err != nil {
1197+
return "", err
1198+
}
11391199
uc := strings.Replace(string(buf), string(0x00), "", -1)
11401200
return uc, nil
11411201
}
@@ -1257,7 +1317,7 @@ func unmarshalECC(buf []byte, kh uintptr) (*ecdsa.PublicKey, error) {
12571317

12581318
// curveName reads the curve name property and returns the corresponding curve.
12591319
func curveName(kh uintptr) (elliptic.Curve, error) {
1260-
cn, err := getProperty(kh, nCryptECCCurveNameProperty)
1320+
cn, err := getPropertyStr(kh, nCryptECCCurveNameProperty)
12611321
if err != nil {
12621322
return nil, fmt.Errorf("unable to determine the curve property name: %v", err)
12631323
}

0 commit comments

Comments
 (0)