2 * Copyright 2009 Henri Verbeet for CodeWeavers
3 * Copyright 2018 Hans Leidekker for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
25 #ifdef HAVE_COMMONCRYPTO_COMMONCRYPTOR_H
26 #include <AvailabilityMacros.h>
27 #include <CommonCrypto/CommonCryptor.h>
31 #define WIN32_NO_STATUS
37 #include "bcrypt_internal.h"
39 #include "wine/debug.h"
40 #include "wine/heap.h"
41 #include "wine/library.h"
42 #include "wine/unicode.h"
44 #if defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 && !defined(HAVE_GNUTLS_CIPHER_INIT)
45 WINE_DEFAULT_DEBUG_CHANNEL(bcrypt
);
47 NTSTATUS
key_set_property( struct key
*key
, const WCHAR
*prop
, UCHAR
*value
, ULONG size
, ULONG flags
)
49 if (!strcmpW( prop
, BCRYPT_CHAINING_MODE
))
51 if (!strcmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_ECB
))
53 key
->u
.s
.mode
= MODE_ID_ECB
;
54 return STATUS_SUCCESS
;
56 else if (!strcmpW( (WCHAR
*)value
, BCRYPT_CHAIN_MODE_CBC
))
58 key
->u
.s
.mode
= MODE_ID_CBC
;
59 return STATUS_SUCCESS
;
63 FIXME( "unsupported mode %s\n", debugstr_w((WCHAR
*)value
) );
64 return STATUS_NOT_IMPLEMENTED
;
68 FIXME( "unsupported key property %s\n", debugstr_w(prop
) );
69 return STATUS_NOT_IMPLEMENTED
;
72 static ULONG
get_block_size( struct algorithm
*alg
)
74 ULONG ret
= 0, size
= sizeof(ret
);
75 get_alg_property( alg
, BCRYPT_BLOCK_LENGTH
, (UCHAR
*)&ret
, sizeof(ret
), &size
);
79 NTSTATUS
key_symmetric_init( struct key
*key
, struct algorithm
*alg
, const UCHAR
*secret
, ULONG secret_len
)
90 FIXME( "mode %u not supported\n", alg
->mode
);
91 return STATUS_NOT_SUPPORTED
;
96 FIXME( "algorithm %u not supported\n", alg
->id
);
97 return STATUS_NOT_SUPPORTED
;
100 if (!(key
->u
.s
.block_size
= get_block_size( alg
))) return STATUS_INVALID_PARAMETER
;
101 if (!(key
->u
.s
.secret
= heap_alloc( secret_len
))) return STATUS_NO_MEMORY
;
102 memcpy( key
->u
.s
.secret
, secret
, secret_len
);
103 key
->u
.s
.secret_len
= secret_len
;
105 key
->alg_id
= alg
->id
;
106 key
->u
.s
.mode
= alg
->mode
;
107 key
->u
.s
.ref_encrypt
= NULL
; /* initialized on first use */
108 key
->u
.s
.ref_decrypt
= NULL
;
109 key
->u
.s
.vector
= NULL
;
110 key
->u
.s
.vector_len
= 0;
112 return STATUS_SUCCESS
;
115 static CCMode
get_cryptor_mode( struct key
*key
)
117 switch (key
->u
.s
.mode
)
119 case MODE_ID_ECB
: return kCCModeECB
;
120 case MODE_ID_CBC
: return kCCModeCBC
;
122 FIXME( "unsupported mode %u\n", key
->u
.s
.mode
);
127 NTSTATUS
key_symmetric_set_vector( struct key
*key
, UCHAR
*vector
, ULONG vector_len
)
129 if (key
->u
.s
.ref_encrypt
&& (!is_zero_vector( vector
, vector_len
) ||
130 !is_equal_vector( key
->u
.s
.vector
, key
->u
.s
.vector_len
, vector
, vector_len
)))
132 TRACE( "invalidating cryptor handles\n" );
133 CCCryptorRelease( key
->u
.s
.ref_encrypt
);
134 key
->u
.s
.ref_encrypt
= NULL
;
136 CCCryptorRelease( key
->u
.s
.ref_decrypt
);
137 key
->u
.s
.ref_decrypt
= NULL
;
140 heap_free( key
->u
.s
.vector
);
141 key
->u
.s
.vector
= NULL
;
142 key
->u
.s
.vector_len
= 0;
145 if (!(key
->u
.s
.vector
= heap_alloc( vector_len
))) return STATUS_NO_MEMORY
;
146 memcpy( key
->u
.s
.vector
, vector
, vector_len
);
147 key
->u
.s
.vector_len
= vector_len
;
150 return STATUS_SUCCESS
;
153 static NTSTATUS
init_cryptor_handles( struct key
*key
)
155 CCCryptorStatus status
;
158 if (key
->u
.s
.ref_encrypt
) return STATUS_SUCCESS
;
159 if (!(mode
= get_cryptor_mode( key
))) return STATUS_NOT_SUPPORTED
;
161 if ((status
= CCCryptorCreateWithMode( kCCEncrypt
, mode
, kCCAlgorithmAES128
, ccNoPadding
, key
->u
.s
.vector
,
162 key
->u
.s
.secret
, key
->u
.s
.secret_len
, NULL
, 0, 0, 0,
163 &key
->u
.s
.ref_encrypt
)) != kCCSuccess
)
165 WARN( "CCCryptorCreateWithMode failed %d\n", status
);
166 return STATUS_INTERNAL_ERROR
;
168 if ((status
= CCCryptorCreateWithMode( kCCDecrypt
, mode
, kCCAlgorithmAES128
, ccNoPadding
, key
->u
.s
.vector
,
169 key
->u
.s
.secret
, key
->u
.s
.secret_len
, NULL
, 0, 0, 0,
170 &key
->u
.s
.ref_decrypt
)) != kCCSuccess
)
172 WARN( "CCCryptorCreateWithMode failed %d\n", status
);
173 CCCryptorRelease( key
->u
.s
.ref_encrypt
);
174 key
->u
.s
.ref_encrypt
= NULL
;
175 return STATUS_INTERNAL_ERROR
;
178 return STATUS_SUCCESS
;
181 NTSTATUS
key_symmetric_set_auth_data( struct key
*key
, UCHAR
*auth_data
, ULONG len
)
183 FIXME( "not implemented on Mac\n" );
184 return STATUS_NOT_IMPLEMENTED
;
187 NTSTATUS
key_symmetric_encrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
, ULONG output_len
)
189 CCCryptorStatus status
;
192 if ((ret
= init_cryptor_handles( key
))) return ret
;
194 if ((status
= CCCryptorUpdate( key
->u
.s
.ref_encrypt
, input
, input_len
, output
, output_len
, NULL
)) != kCCSuccess
)
196 WARN( "CCCryptorUpdate failed %d\n", status
);
197 return STATUS_INTERNAL_ERROR
;
199 return STATUS_SUCCESS
;
202 NTSTATUS
key_symmetric_decrypt( struct key
*key
, const UCHAR
*input
, ULONG input_len
, UCHAR
*output
, ULONG output_len
)
204 CCCryptorStatus status
;
207 if ((ret
= init_cryptor_handles( key
))) return ret
;
209 if ((status
= CCCryptorUpdate( key
->u
.s
.ref_decrypt
, input
, input_len
, output
, output_len
, NULL
)) != kCCSuccess
)
211 WARN( "CCCryptorUpdate failed %d\n", status
);
212 return STATUS_INTERNAL_ERROR
;
214 return STATUS_SUCCESS
;
217 NTSTATUS
key_symmetric_get_tag( struct key
*key
, UCHAR
*tag
, ULONG len
)
219 FIXME( "not implemented on Mac\n" );
220 return STATUS_NOT_IMPLEMENTED
;
223 NTSTATUS
key_asymmetric_init( struct key
*key
, struct algorithm
*alg
, ULONG bitlen
, const UCHAR
*pubkey
,
226 FIXME( "not implemented on Mac\n" );
227 return STATUS_NOT_IMPLEMENTED
;
230 NTSTATUS
key_asymmetric_sign( struct key
*key
, void *padding
, UCHAR
*input
, ULONG input_len
, UCHAR
*output
,
231 ULONG output_len
, ULONG
*ret_len
, ULONG flags
)
233 FIXME( "not implemented on Mac\n" );
234 return STATUS_NOT_IMPLEMENTED
;
237 NTSTATUS
key_asymmetric_verify( struct key
*key
, void *padding
, UCHAR
*hash
, ULONG hash_len
, UCHAR
*signature
,
238 ULONG signature_len
, DWORD flags
)
240 FIXME( "not implemented on Mac\n" );
241 return STATUS_NOT_IMPLEMENTED
;
244 NTSTATUS
key_export_ecc( struct key
*key
, UCHAR
*output
, ULONG len
, ULONG
*ret_len
)
246 FIXME( "not implemented on Mac\n" );
247 return STATUS_NOT_IMPLEMENTED
;
250 NTSTATUS
key_import_ecc( struct key
*key
, UCHAR
*input
, ULONG len
)
252 FIXME( "not implemented on Mac\n" );
253 return STATUS_NOT_IMPLEMENTED
;
256 NTSTATUS
key_asymmetric_generate( struct key
*key
)
258 FIXME( "not implemented on Mac\n" );
259 return STATUS_NOT_IMPLEMENTED
;
262 NTSTATUS
key_destroy( struct key
*key
)
264 if (key
->u
.s
.ref_encrypt
) CCCryptorRelease( key
->u
.s
.ref_encrypt
);
265 if (key
->u
.s
.ref_decrypt
) CCCryptorRelease( key
->u
.s
.ref_decrypt
);
266 heap_free( key
->u
.s
.vector
);
267 heap_free( key
->u
.s
.secret
);
269 return STATUS_SUCCESS
;