@@ -113,6 +113,14 @@ var (
113
113
nCryptAlgorithmGroupProperty = wide ("Algorithm Group" ) // NCRYPT_ALGORITHM_GROUP_PROPERTY
114
114
nCryptUniqueNameProperty = wide ("Unique Name" ) // NCRYPT_UNIQUE_NAME_PROPERTY
115
115
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
116
124
117
125
// curveIDs maps bcrypt key blob magic numbers to elliptic curves.
118
126
curveIDs = map [uint32 ]elliptic.Curve {
@@ -413,15 +421,19 @@ func (w *WinCertStore) cert(issuers []string, searchRoot *uint16, store uint32)
413
421
return cert , prev , nil
414
422
}
415
423
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 )
419
426
if r == 0 {
420
427
return nil
421
428
}
422
429
return fmt .Errorf ("NCryptFreeObject returned %X: %v" , r , err )
423
430
}
424
431
432
+ // Close frees the handle to the certificate provider
433
+ func (w * WinCertStore ) Close () error {
434
+ return freeObject (w .Prov )
435
+ }
436
+
425
437
// Link will associate the certificate installed in the system store to the user store.
426
438
func (w * WinCertStore ) Link () error {
427
439
cert , _ , err := w .cert (w .issuers , my , certStoreLocalMachine )
@@ -1066,21 +1078,39 @@ func (w *WinCertStore) generateRSA(keySize int) (crypto.Signer, error) {
1066
1078
1067
1079
func keyMetadata (kh uintptr , store * WinCertStore ) (* Key , error ) {
1068
1080
// 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 )
1070
1082
if err != nil {
1071
1083
return nil , fmt .Errorf ("unable to determine key unique name: %v" , err )
1072
1084
}
1073
1085
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
+
1074
1099
// Populate key storage locations for software backed keys.
1075
1100
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 {
1077
1107
uc , lc , err = softwareKeyContainers (uc )
1078
1108
if err != nil {
1079
1109
return nil , err
1080
1110
}
1081
1111
}
1082
1112
1083
- alg , err := getProperty (kh , nCryptAlgorithmGroupProperty )
1113
+ alg , err := getPropertyStr (kh , nCryptAlgorithmGroupProperty )
1084
1114
if err != nil {
1085
1115
return nil , fmt .Errorf ("unable to determine key algorithm: %v" , err )
1086
1116
}
@@ -1109,7 +1139,7 @@ func keyMetadata(kh uintptr, store *WinCertStore) (*Key, error) {
1109
1139
return & Key {handle : kh , pub : pub , Container : uc , LegacyContainer : lc , AlgorithmGroup : alg }, nil
1110
1140
}
1111
1141
1112
- func getProperty (kh uintptr , property * uint16 ) (string , error ) {
1142
+ func getProperty (kh uintptr , property * uint16 ) ([] byte , error ) {
1113
1143
var strSize uint32
1114
1144
r , _ , err := nCryptGetProperty .Call (
1115
1145
kh ,
@@ -1120,7 +1150,7 @@ func getProperty(kh uintptr, property *uint16) (string, error) {
1120
1150
0 ,
1121
1151
0 )
1122
1152
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 )
1124
1154
}
1125
1155
1126
1156
buf := make ([]byte , strSize )
@@ -1133,9 +1163,39 @@ func getProperty(kh uintptr, property *uint16) (string, error) {
1133
1163
0 ,
1134
1164
0 )
1135
1165
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 )
1137
1167
}
1138
1168
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
+ }
1139
1199
uc := strings .Replace (string (buf ), string (0x00 ), "" , - 1 )
1140
1200
return uc , nil
1141
1201
}
@@ -1257,7 +1317,7 @@ func unmarshalECC(buf []byte, kh uintptr) (*ecdsa.PublicKey, error) {
1257
1317
1258
1318
// curveName reads the curve name property and returns the corresponding curve.
1259
1319
func curveName (kh uintptr ) (elliptic.Curve , error ) {
1260
- cn , err := getProperty (kh , nCryptECCCurveNameProperty )
1320
+ cn , err := getPropertyStr (kh , nCryptECCCurveNameProperty )
1261
1321
if err != nil {
1262
1322
return nil , fmt .Errorf ("unable to determine the curve property name: %v" , err )
1263
1323
}
0 commit comments