-
Notifications
You must be signed in to change notification settings - Fork 28
Add support for additional CAPI certificate context properties #873
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
7a9ba71
59ed40b
f459ee2
e785b6c
2d843f0
e7322a2
de60c2a
ee6fd1a
5461460
cb11e69
b42b536
c899aeb
dcefc6c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -62,9 +62,11 @@ const ( | |
| compareShift = 16 // CERT_COMPARE_SHIFT | ||
| compareSHA1Hash = 1 // CERT_COMPARE_SHA1_HASH | ||
| compareCertID = 16 // CERT_COMPARE_CERT_ID | ||
| compareProp = 5 // CERT_COMPARE_CERT_ID | ||
| findIssuerStr = compareNameStrW<<compareShift | infoIssuerFlag // CERT_FIND_ISSUER_STR_W | ||
| findIssuerName = compareName<<compareShift | infoIssuerFlag // CERT_FIND_ISSUER_NAME | ||
| findHash = compareSHA1Hash << compareShift // CERT_FIND_HASH | ||
| findProperty = compareProp << compareShift // CERT_FIND_PROPERTY | ||
| findCertID = compareCertID << compareShift // CERT_FIND_CERT_ID | ||
|
|
||
| signatureKeyUsage = 0x80 // CERT_DIGITAL_SIGNATURE_KEY_USAGE | ||
|
|
@@ -84,6 +86,8 @@ const ( | |
| CERT_ID_SHA1_HASH = uint32(3) | ||
|
|
||
| CERT_KEY_PROV_INFO_PROP_ID = uint32(2) | ||
| CERT_FRIENDLY_NAME_PROP_ID = uint32(11) | ||
| CERT_DESCRIPTION_PROP_ID = uint32(13) | ||
|
|
||
| CERT_NAME_STR_COMMA_FLAG = uint32(0x04000000) | ||
| CERT_SIMPLE_NAME_STR = uint32(1) | ||
|
|
@@ -153,6 +157,7 @@ var ( | |
| procCertFindCertificateInStore = crypt32.MustFindProc("CertFindCertificateInStore") | ||
| procCryptFindCertificateKeyProvInfo = crypt32.MustFindProc("CryptFindCertificateKeyProvInfo") | ||
| procCertGetCertificateContextProperty = crypt32.MustFindProc("CertGetCertificateContextProperty") | ||
| procCertSetCertificateContextProperty = crypt32.MustFindProc("CertSetCertificateContextProperty") | ||
| procCertStrToName = crypt32.MustFindProc("CertStrToNameW") | ||
| ) | ||
|
|
||
|
|
@@ -633,6 +638,102 @@ func cryptFindCertificateKeyContainerName(certContext *windows.CertContext) (str | |
| return "", nil | ||
| } | ||
|
|
||
| func certSetCertificateContextProperty(certContext *windows.CertContext, propID uint32, pvData uintptr) error { | ||
| r0, _, err := procCertSetCertificateContextProperty.Call( | ||
| uintptr(unsafe.Pointer(certContext)), | ||
| uintptr(propID), | ||
| 0, | ||
| pvData, | ||
| ) | ||
|
|
||
| if r0 == 0 { | ||
| return err | ||
| } | ||
| return nil | ||
|
Comment on lines
+649
to
+652
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This invokes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to the above, I think comments helps a lot here. |
||
| } | ||
|
|
||
| func cryptSetCertificateFriendlyName(certContext *windows.CertContext, val string) error { | ||
| data := CRYPTOAPI_BLOB{ | ||
| len: uint32(len(val)+1) * 2, | ||
| data: uintptr(unsafe.Pointer(wide(val))), | ||
| } | ||
|
|
||
| return certSetCertificateContextProperty(certContext, CERT_FRIENDLY_NAME_PROP_ID, uintptr(unsafe.Pointer(&data))) | ||
| } | ||
|
|
||
| func cryptSetCertificateDescription(certContext *windows.CertContext, val string) error { | ||
| data := CRYPTOAPI_BLOB{ | ||
| len: uint32(len(val)+1) * 2, | ||
| data: uintptr(unsafe.Pointer(wide(val))), | ||
| } | ||
|
|
||
| return certSetCertificateContextProperty(certContext, CERT_DESCRIPTION_PROP_ID, uintptr(unsafe.Pointer(&data))) | ||
| } | ||
|
|
||
| func certGetCertificateContextProperty(certContext *windows.CertContext, propID uint32, pvData *byte, pcbData *uint32) error { | ||
| r0, _, err := procCertGetCertificateContextProperty.Call( | ||
| uintptr(unsafe.Pointer(certContext)), | ||
| uintptr(propID), | ||
| uintptr(unsafe.Pointer(pvData)), | ||
| uintptr(unsafe.Pointer(pcbData)), | ||
| ) | ||
| if r0 == 0 { | ||
| return err | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func cryptFindCertificateFriendlyName(certContext *windows.CertContext) (string, error) { | ||
| var size uint32 | ||
|
|
||
| err := certGetCertificateContextProperty(certContext, CERT_FRIENDLY_NAME_PROP_ID, nil, &size) | ||
| if err != nil { | ||
| if errno, ok := err.(windows.Errno); ok && uint32(errno) == CRYPT_E_NOT_FOUND { | ||
| return "", nil | ||
| } | ||
|
|
||
| return "", err | ||
| } | ||
|
|
||
| if size == 0 { | ||
| return "", nil | ||
| } | ||
|
|
||
| buf := make([]byte, size) | ||
| err = certGetCertificateContextProperty(certContext, CERT_FRIENDLY_NAME_PROP_ID, &buf[0], &size) | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
|
|
||
| uc := bytes.ReplaceAll(buf, []byte{0x00}, []byte("")) | ||
| return string(uc), nil | ||
| } | ||
|
|
||
| func cryptFindCertificateDescription(certContext *windows.CertContext) (string, error) { | ||
| var size uint32 | ||
|
|
||
| err := certGetCertificateContextProperty(certContext, CERT_DESCRIPTION_PROP_ID, nil, &size) | ||
| if err != nil { | ||
| if errno, ok := err.(windows.Errno); ok && uint32(errno) == CRYPT_E_NOT_FOUND { | ||
| return "", nil | ||
| } | ||
|
|
||
| return "", err | ||
| } | ||
| if size == 0 { | ||
| return "", nil | ||
| } | ||
|
|
||
| buf := make([]byte, size) | ||
| err = certGetCertificateContextProperty(certContext, CERT_DESCRIPTION_PROP_ID, &buf[0], &size) | ||
| if err != nil { | ||
| return "", err | ||
| } | ||
|
|
||
| uc := bytes.ReplaceAll(buf, []byte{0x00}, []byte("")) | ||
| return string(uc), nil | ||
| } | ||
|
|
||
| func certStrToName(x500Str string) ([]byte, error) { | ||
| var size uint32 | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is
r0? I think this could use a more descriptive name.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually r1, this invokes a system call on windows (whose procedure is found in a DLL), the system call returns r1, r2, error, in general, where r1 represents the return value status from the procedure stored in a register (e.g. on Linux the %rax value), the semantic value of this depends on the procedure invoked, r2 is usually not used but kept for compatibility with platforms that return status on more registers, and the 3rd value return is actually an error, on windows the error is always non nil so we must check r0(r1).
I think we can leave this low level stuff as is, or perhaps considering refactor this in another pr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, that all makes sense. Can you add a comment to these funcs explaining it? With the information you provided above, it's clear, but without it, it's not clear what's happening.