2 * Copyright (c) 2020 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/IOLib.h>
30 #include <kern/debug.h> // for panic()
32 #include <libkern/ptrauth_utils.h>
35 #if __has_feature(ptrauth_calls)
38 * ptrauth_utils_sign_blob_generic
40 * Sign a blob of data with the GA key
43 __attribute__((noinline
))
44 ptrauth_generic_signature_t
45 ptrauth_utils_sign_blob_generic(const void * ptr
, size_t len_bytes
, uint64_t data
, int flags
)
47 ptrauth_generic_signature_t sig
= 0;
49 uint64_t rounds
= len_bytes
/ sizeof(uintptr_t);
50 size_t ntrailing
= len_bytes
% sizeof(uintptr_t);
51 uintptr_t trailing
= 0;
57 /* If address diversification is requested, mix the blob address with the salt */
58 if (flags
& PTRAUTH_ADDR_DIVERSIFY
) {
59 data
^= (uint64_t)ptr
;
62 /* First round adds ptrauth_utils_sign_blob_generic discrimination. */
63 sig
= ptrauth_sign_generic_data(sig
, ptrauth_string_discriminator("ptrauth_utils_sign_blob_generic-prologue") | 0x01);
65 /* Second round adds salt */
66 sig
= ptrauth_sign_generic_data(sig
, data
);
68 /* Calculate an additive signature of the buffer */
69 for (uint64_t i
= 0; i
< rounds
; i
++) {
70 sig
= ptrauth_sign_generic_data(*(const uintptr_t *)ptr
, sig
);
71 ptr
+= sizeof(uintptr_t);
74 /* ptrauth_sign_generic_data operates on pointer-sized values only,
75 * so we need to handle trailing bytes for the non-pointer-aligned case */
77 for (int i
= 0; i
< ntrailing
; i
++) {
78 ((uint8_t *)&trailing
)[i
] = ((const uint8_t *)ptr
)[i
];
80 sig
= ptrauth_sign_generic_data(trailing
, sig
);
84 /* Final round to add an additional cookie */
85 sig
= ptrauth_sign_generic_data(sig
, ptrauth_string_discriminator("ptrauth_utils_sign_blob_generic-epilogue") | 0x01);
91 * ptrauth_utils_auth_blob_generic
93 * Authenticate signature produced by ptrauth_utils_sign_blob_generic
95 __attribute__((noinline
))
97 ptrauth_utils_auth_blob_generic(const void * ptr
, size_t len_bytes
, uint64_t data
, int flags
, ptrauth_generic_signature_t signature
)
99 ptrauth_generic_signature_t calculated_signature
= 0;
102 if (flags
& PTRAUTH_NON_NULL
) {
103 panic("ptrauth_utils_auth_blob_generic: ptr must not be NULL");
109 if ((calculated_signature
= ptrauth_utils_sign_blob_generic(ptr
, len_bytes
, data
, flags
)) == signature
) {
112 panic("signature mismatch for %lu bytes at %p, calculated %lx vs %lx", len_bytes
,
114 calculated_signature
,
119 #endif //!ptrauth_calls