122 {
123 SecAccessControlRef accessControlRef = SecAccessControlCreateWithFlags(nullptr, kSecAttrAccessibleWhenUnlockedThisDeviceOnly, kSecAccessControlPrivateKeyUsage, nullptr);
124
125 int keySizeValue = 256;
126 CFNumberRef keySizeNumber = CFNumberCreate(NULL, kCFNumberIntType, &keySizeValue);
127
128 const void* keyAttrKeys[] = {
129 kSecAttrIsPermanent,
130 kSecAttrAccessControl,
131 kSecAttrAccessGroup
132 };
133 const void* keyAttrValues[] = {
134 kCFBooleanTrue,
135 accessControlRef,
136#ifdef MAS_KEYCHAIN_GROUP
137 CFSTR(
XSTR(MAS_KEYCHAIN_GROUP))
138#endif
139 };
140 CFDictionaryRef keyAttrDic = CFDictionaryCreate(NULL, keyAttrKeys, keyAttrValues, sizeof(keyAttrValues)/sizeof(keyAttrValues[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
141
142 const void* attrKeys[] = {
143 kSecAttrKeyType,
144 kSecAttrKeySizeInBits,
145 kSecAttrTokenID,
146 kSecPrivateKeyAttrs
147 };
148 const void* atrrValues[] = {
149 kSecAttrKeyTypeECSECPrimeRandom,
150 keySizeNumber,
151 kSecAttrTokenIDSecureEnclave,
152 keyAttrDic
153 };
154 CFDictionaryRef attributesDic = CFDictionaryCreate(NULL, attrKeys, atrrValues, sizeof(attrKeys)/sizeof(attrKeys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
155
156 CFErrorRef error = NULL;
157 SecKeyRef privateKey = SecKeyCreateRandomKey(attributesDic, &error);
158 string error_string;
159 if(error) {
161 CFRelease(error);
162 }
163
164 CFRelease(attributesDic);
165 CFRelease(keyAttrDic);
166 CFRelease(keySizeNumber);
167 CFRelease(accessControlRef);
168
169 if(error_string.size())
170 FC_THROW_EXCEPTION(chain::wallet_exception,
"Failed to create key in Secure Enclave: ${m}", (
"m", error_string));
171
173 try {
175 }
176 catch(chain::wallet_exception&) {
177
178 CFRelease(privateKey);
179 throw;
180 }
183 }
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
static public_key_type get_public_key(SecKeyRef key)
static string string_for_cferror(CFErrorRef error)