Skip to content
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

Add store and load certificates in mackms #455

Merged
merged 8 commits into from Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 17 additions & 1 deletion internal/darwin/corefoundation/core_foundation_darwin.go
Expand Up @@ -20,9 +20,15 @@
package corefoundation

/*
#cgo LDFLAGS: -framework CoreFoundation
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework CoreFoundation -framework Foundation

#include <Foundation/Foundation.h>
#include <CoreFoundation/CoreFoundation.h>

void nslog(CFTypeRef ref) {
NSLog(@"%@", ref);
}
*/
import "C"
import (
Expand Down Expand Up @@ -159,6 +165,12 @@ func NewDictionary(m Dictionary) (*DictionaryRef, error) {
}, nil
}

func NewDictionaryRef(ref TypeRef) *DictionaryRef {
return &DictionaryRef{
Value: C.CFDictionaryRef(ref),
}
}

func (v *DictionaryRef) Release() { Release(v) }
func (v *DictionaryRef) TypeRef() CFTypeRef { return C.CFTypeRef(v.Value) }

Expand All @@ -181,3 +193,7 @@ func (e ErrorRef) Error() string {

func (e ErrorRef) Release() { Release(e) }
func (e ErrorRef) TypeRef() CFTypeRef { return C.CFTypeRef(C.CFErrorRef(e)) }

func Log(v TypeReferer) {
C.nslog(v.TypeRef())
}
hslatman marked this conversation as resolved.
Show resolved Hide resolved
63 changes: 59 additions & 4 deletions internal/darwin/security/security_darwin.go
Expand Up @@ -38,12 +38,18 @@ const (
nilSecKey C.SecKeyRef = 0
nilSecAccessControl C.SecAccessControlRef = 0
nilCFString C.CFStringRef = 0
nilCFData C.CFDataRef = 0
)

var ErrNotFound = errors.New("not found")
var (
ErrNotFound = errors.New("not found")
ErrAlreadyExists = errors.New("already exists")
ErrInvalidData = errors.New("invalid data")
)

var (
KSecAttrAccessControl = cf.TypeRef(C.kSecAttrAccessControl)
KSecAttrAccessGroup = cf.TypeRef(C.kSecAttrAccessGroup)
KSecAttrAccessibleWhenUnlocked = cf.TypeRef(C.kSecAttrAccessibleWhenUnlocked)
KSecAttrAccessibleWhenPasscodeSetThisDeviceOnly = cf.TypeRef(C.kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly)
KSecAttrAccessibleWhenUnlockedThisDeviceOnly = cf.TypeRef(C.kSecAttrAccessibleWhenUnlockedThisDeviceOnly)
Expand All @@ -62,14 +68,23 @@ var (
KSecAttrLabel = cf.TypeRef(C.kSecAttrLabel)
KSecAttrTokenID = cf.TypeRef(C.kSecAttrTokenID)
KSecAttrTokenIDSecureEnclave = cf.TypeRef(C.kSecAttrTokenIDSecureEnclave)
KSecAttrSerialNumber = cf.TypeRef(C.kSecAttrSerialNumber)
KSecAttrSubjectKeyID = cf.TypeRef(C.kSecAttrSubjectKeyID)
KSecAttrSubject = cf.TypeRef(C.kSecAttrSubject)
KSecAttrIssuer = cf.TypeRef(C.kSecAttrIssuer)
kSecAttrSynchronizable = cf.TypeRef(C.kSecAttrSynchronizable)
kSecUseDataProtectionKeychain = cf.TypeRef(C.kSecUseDataProtectionKeychain)
hslatman marked this conversation as resolved.
Show resolved Hide resolved
KSecClass = cf.TypeRef(C.kSecClass)
KSecClassKey = cf.TypeRef(C.kSecClassKey)
KSecClassCertificate = cf.TypeRef(C.kSecClassCertificate)
KSecClassIdentity = cf.TypeRef(C.kSecClassIdentity)
KSecMatchLimit = cf.TypeRef(C.kSecMatchLimit)
KSecMatchLimitOne = cf.TypeRef(C.kSecMatchLimitOne)
KSecPublicKeyAttrs = cf.TypeRef(C.kSecPublicKeyAttrs)
KSecPrivateKeyAttrs = cf.TypeRef(C.kSecPrivateKeyAttrs)
KSecReturnRef = cf.TypeRef(C.kSecReturnRef)
KSecValueRef = cf.TypeRef(C.kSecValueRef)
KSecValueData = cf.TypeRef(C.kSecValueData)
)

type SecKeyAlgorithm = C.SecKeyAlgorithm
Expand Down Expand Up @@ -135,6 +150,19 @@ func NewSecKeyRef(ref cf.TypeRef) *SecKeyRef {
func (v *SecKeyRef) Release() { cf.Release(v) }
func (v *SecKeyRef) TypeRef() cf.CFTypeRef { return cf.CFTypeRef(v.Value) }

type SecCertificateRef struct {
Value C.SecCertificateRef
}

func NewSecCertificateRef(ref cf.TypeRef) *SecCertificateRef {
return &SecCertificateRef{
Value: C.SecCertificateRef(ref),
}
}

func (v *SecCertificateRef) Release() { cf.Release(v) }
func (v *SecCertificateRef) TypeRef() cf.CFTypeRef { return cf.CFTypeRef(v.Value) }

type SecAccessControlRef struct {
ref C.SecAccessControlRef
}
Expand All @@ -147,6 +175,11 @@ func SecItemAdd(attributes *cf.DictionaryRef, result *cf.TypeRef) error {
return goOSStatus(status)
}

func SecItemUpdate(query *cf.DictionaryRef, attributesToUpdate *cf.DictionaryRef) error {
status := C.SecItemUpdate(C.CFDictionaryRef(query.Value), C.CFDictionaryRef(attributesToUpdate.Value))
return goOSStatus(status)
}

func SecItemDelete(query *cf.DictionaryRef) error {
status := C.SecItemDelete(C.CFDictionaryRef(query.Value))
return goOSStatus(status)
Expand Down Expand Up @@ -218,6 +251,26 @@ func SecKeyCreateSignature(key *SecKeyRef, algorithm SecKeyAlgorithm, dataToSign
}, nil
}

func SecCertificateCopyData(cert *SecCertificateRef) (*cf.DataRef, error) {
data := C.SecCertificateCopyData(cert.Value)
if data == nilCFData {
return nil, ErrInvalidData
}
return &cf.DataRef{
Value: cf.CFDataRef(data),
}, nil
}

func SecCertificateCreateWithData(certData *cf.DataRef) (*SecCertificateRef, error) {
certRef := C.SecCertificateCreateWithData(C.kCFAllocatorDefault, C.CFDataRef(certData.Value))
if certRef == 0 {
return nil, ErrInvalidData
}
return &SecCertificateRef{
Value: certRef,
}, nil
}

func SecCopyErrorMessageString(status C.OSStatus) *cf.StringRef {
s := C.SecCopyErrorMessageString(status, nil)
return &cf.StringRef{
Expand Down Expand Up @@ -254,11 +307,13 @@ func (e osStatusError) Error() string {
}

func goOSStatus(status C.OSStatus) error {
if status == 0 {
switch status {
case 0:
return nil
}
if status == C.errSecItemNotFound {
case C.errSecItemNotFound: // -25300
return ErrNotFound
case C.errSecDuplicateItem: // -25299
return ErrAlreadyExists
}

var message string
Expand Down
13 changes: 12 additions & 1 deletion kms/apiv1/requests.go
Expand Up @@ -131,7 +131,7 @@ type GetPublicKeyRequest struct {
type CreateKeyRequest struct {
// Name represents the key name or label used to identify a key.
//
// Used by: awskms, cloudkms, azurekms, pkcs11, yubikey, tpmkms.
// Used by: awskms, cloudkms, azurekms, pkcs11, yubikey, tpmkms, mackms.
Name string

// SignatureAlgorithm represents the type of key to create.
Expand Down Expand Up @@ -298,3 +298,14 @@ type CreateAttestationResponse struct {
type DeleteKeyRequest struct {
Name string
}

// DeleteCertificateRequest is the parameter used in the kms.DeleteCertificate
// method.
//
// # Experimental
//
// Notice: This API is EXPERIMENTAL and may be changed or removed in a later
// release.
type DeleteCertificateRequest struct {
Name string
}