add darwin/xnu functionality

This commit is contained in:
Sam Sneed 2024-06-03 11:29:39 -05:00
parent 58217f5900
commit f5727805f2
2105 changed files with 1224193 additions and 4 deletions

View file

@ -12,7 +12,7 @@ echo "Building basic keyboard support"
nasm -f elf32 source/detect-kbinput.asm -o builds/blocks/detectkeys.o
echo "Building OS"
set disassembly-flavor intel
opt/cross/bin/i686-elf-gcc builds/blocks/bootloader.o -ffreestanding -nostdlib builds/blocks/detectkeys.o source/os.c -w -g -m32 -o builds/iso/gems.elf -I"/usr/include" -I"source/THIRDPARTY/lwext4-master/include/" -I"source/THIRDPARTY/linux-old/include/linux" -I"source/THIRDPARTY/linux-old/include/asm"
opt/cross/bin/i686-elf-gcc builds/blocks/bootloader.o -ffreestanding -nostdlib builds/blocks/detectkeys.o source/os.c -w -g -m32 -o builds/iso/gems.elf -I"/usr/include" -I"source/THIRDPARTY/lwext4-master/include/" -I"source/THIRDPARTY/linux-old/include/linux" -I"source/THIRDPARTY/linux-old/include/asm" -I"source/THIRDPARTY/xnu/EXTERNAL_HEADERS" -I"source/THIRDPARTY/xnu/libkern" -I"source/THIRDPARTY/xnu/security" -I"source/THIRDPARTY/xnu/bsd"
echo "Creating GRUB config"
echo "set default=0" > builds/iso/boot/grub/grub.cfg
echo "set timeout=60" >> builds/iso/boot/grub/grub.cfg

View file

@ -1 +1 @@
sudo apt install xorriso libc6-dev-i386
sudo apt install xorriso libc6-dev-i386 nasm

View file

@ -0,0 +1,367 @@
APPLE PUBLIC SOURCE LICENSE
Version 2.0 - August 6, 2003
Please read this License carefully before downloading this software.
By downloading or using this software, you are agreeing to be bound by
the terms of this License. If you do not or cannot agree to the terms
of this License, please do not download or use the software.
1. General; Definitions. This License applies to any program or other
work which Apple Computer, Inc. ("Apple") makes publicly available and
which contains a notice placed by Apple identifying such program or
work as "Original Code" and stating that it is subject to the terms of
this Apple Public Source License version 2.0 ("License"). As used in
this License:
1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is
the grantor of rights, (i) claims of patents that are now or hereafter
acquired, owned by or assigned to Apple and (ii) that cover subject
matter contained in the Original Code, but only to the extent
necessary to use, reproduce and/or distribute the Original Code
without infringement; and (b) in the case where You are the grantor of
rights, (i) claims of patents that are now or hereafter acquired,
owned by or assigned to You and (ii) that cover subject matter in Your
Modifications, taken alone or in combination with Original Code.
1.2 "Contributor" means any person or entity that creates or
contributes to the creation of Modifications.
1.3 "Covered Code" means the Original Code, Modifications, the
combination of Original Code and any Modifications, and/or any
respective portions thereof.
1.4 "Externally Deploy" means: (a) to sublicense, distribute or
otherwise make Covered Code available, directly or indirectly, to
anyone other than You; and/or (b) to use Covered Code, alone or as
part of a Larger Work, in any way to provide a service, including but
not limited to delivery of content, through electronic communication
with a client other than You.
1.5 "Larger Work" means a work which combines Covered Code or portions
thereof with code not governed by the terms of this License.
1.6 "Modifications" mean any addition to, deletion from, and/or change
to, the substance and/or structure of the Original Code, any previous
Modifications, the combination of Original Code and any previous
Modifications, and/or any respective portions thereof. When code is
released as a series of files, a Modification is: (a) any addition to
or deletion from the contents of a file containing Covered Code;
and/or (b) any new file or other representation of computer program
statements that contains any part of Covered Code.
1.7 "Original Code" means (a) the Source Code of a program or other
work as originally made available by Apple under this License,
including the Source Code of any updates or upgrades to such programs
or works made available by Apple under this License, and that has been
expressly identified by Apple as such in the header file(s) of such
work; and (b) the object code compiled from such Source Code and
originally made available by Apple under this License.
1.8 "Source Code" means the human readable form of a program or other
work that is suitable for making modifications to it, including all
modules it contains, plus any associated interface definition files,
scripts used to control compilation and installation of an executable
(object code).
1.9 "You" or "Your" means an individual or a legal entity exercising
rights under this License. For legal entities, "You" or "Your"
includes any entity which controls, is controlled by, or is under
common control with, You, where "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of fifty percent
(50%) or more of the outstanding shares or beneficial ownership of
such entity.
2. Permitted Uses; Conditions & Restrictions. Subject to the terms
and conditions of this License, Apple hereby grants You, effective on
the date You accept this License and download the Original Code, a
world-wide, royalty-free, non-exclusive license, to the extent of
Apple's Applicable Patent Rights and copyrights covering the Original
Code, to do the following:
2.1 Unmodified Code. You may use, reproduce, display, perform,
internally distribute within Your organization, and Externally Deploy
verbatim, unmodified copies of the Original Code, for commercial or
non-commercial purposes, provided that in each instance:
(a) You must retain and reproduce in all copies of Original Code the
copyright and other proprietary notices and disclaimers of Apple as
they appear in the Original Code, and keep intact all notices in the
Original Code that refer to this License; and
(b) You must include a copy of this License with every copy of Source
Code of Covered Code and documentation You distribute or Externally
Deploy, and You may not offer or impose any terms on such Source Code
that alter or restrict this License or the recipients' rights
hereunder, except as permitted under Section 6.
2.2 Modified Code. You may modify Covered Code and use, reproduce,
display, perform, internally distribute within Your organization, and
Externally Deploy Your Modifications and Covered Code, for commercial
or non-commercial purposes, provided that in each instance You also
meet all of these conditions:
(a) You must satisfy all the conditions of Section 2.1 with respect to
the Source Code of the Covered Code;
(b) You must duplicate, to the extent it does not already exist, the
notice in Exhibit A in each file of the Source Code of all Your
Modifications, and cause the modified files to carry prominent notices
stating that You changed the files and the date of any change; and
(c) If You Externally Deploy Your Modifications, You must make
Source Code of all Your Externally Deployed Modifications either
available to those to whom You have Externally Deployed Your
Modifications, or publicly available. Source Code of Your Externally
Deployed Modifications must be released under the terms set forth in
this License, including the license grants set forth in Section 3
below, for as long as you Externally Deploy the Covered Code or twelve
(12) months from the date of initial External Deployment, whichever is
longer. You should preferably distribute the Source Code of Your
Externally Deployed Modifications electronically (e.g. download from a
web site).
2.3 Distribution of Executable Versions. In addition, if You
Externally Deploy Covered Code (Original Code and/or Modifications) in
object code, executable form only, You must include a prominent
notice, in the code itself as well as in related documentation,
stating that Source Code of the Covered Code is available under the
terms of this License with information on how and where to obtain such
Source Code.
2.4 Third Party Rights. You expressly acknowledge and agree that
although Apple and each Contributor grants the licenses to their
respective portions of the Covered Code set forth herein, no
assurances are provided by Apple or any Contributor that the Covered
Code does not infringe the patent or other intellectual property
rights of any other entity. Apple and each Contributor disclaim any
liability to You for claims brought by any other entity based on
infringement of intellectual property rights or otherwise. As a
condition to exercising the rights and licenses granted hereunder, You
hereby assume sole responsibility to secure any other intellectual
property rights needed, if any. For example, if a third party patent
license is required to allow You to distribute the Covered Code, it is
Your responsibility to acquire that license before distributing the
Covered Code.
3. Your Grants. In consideration of, and as a condition to, the
licenses granted to You under this License, You hereby grant to any
person or entity receiving or distributing Covered Code under this
License a non-exclusive, royalty-free, perpetual, irrevocable license,
under Your Applicable Patent Rights and other intellectual property
rights (other than patent) owned or controlled by You, to use,
reproduce, display, perform, modify, sublicense, distribute and
Externally Deploy Your Modifications of the same scope and extent as
Apple's licenses under Sections 2.1 and 2.2 above.
4. Larger Works. You may create a Larger Work by combining Covered
Code with other code not governed by the terms of this License and
distribute the Larger Work as a single product. In each such instance,
You must make sure the requirements of this License are fulfilled for
the Covered Code or any portion thereof.
5. Limitations on Patent License. Except as expressly stated in
Section 2, no other patent rights, express or implied, are granted by
Apple herein. Modifications and/or Larger Works may require additional
patent licenses from Apple which Apple may grant in its sole
discretion.
6. Additional Terms. You may choose to offer, and to charge a fee for,
warranty, support, indemnity or liability obligations and/or other
rights consistent with the scope of the license granted herein
("Additional Terms") to one or more recipients of Covered Code.
However, You may do so only on Your own behalf and as Your sole
responsibility, and not on behalf of Apple or any Contributor. You
must obtain the recipient's agreement that any such Additional Terms
are offered by You alone, and You hereby agree to indemnify, defend
and hold Apple and every Contributor harmless for any liability
incurred by or claims asserted against Apple or such Contributor by
reason of any such Additional Terms.
7. Versions of the License. Apple may publish revised and/or new
versions of this License from time to time. Each version will be given
a distinguishing version number. Once Original Code has been published
under a particular version of this License, You may continue to use it
under the terms of that version. You may also choose to use such
Original Code under the terms of any subsequent version of this
License published by Apple. No one other than Apple has the right to
modify the terms applicable to Covered Code created under this
License.
8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in
part pre-release, untested, or not fully tested works. The Covered
Code may contain errors that could cause failures or loss of data, and
may be incomplete or contain inaccuracies. You expressly acknowledge
and agree that use of the Covered Code, or any portion thereof, is at
Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND
WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND
APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE
PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT
NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF
MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR
PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD
PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST
INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE
FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS,
THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO
ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE
AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.
You acknowledge that the Covered Code is not intended for use in the
operation of nuclear facilities, aircraft navigation, communication
systems, or air traffic control machines in which case the failure of
the Covered Code could lead to death, personal injury, or severe
physical or environmental damage.
9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL,
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING
TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR
ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY,
TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF
APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY
REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF
INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY
TO YOU. In no event shall Apple's total liability to You for all
damages (other than as may be required by applicable law) under this
License exceed the amount of fifty dollars ($50.00).
10. Trademarks. This License does not grant any rights to use the
trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS",
"QuickTime", "QuickTime Streaming Server" or any other trademarks,
service marks, logos or trade names belonging to Apple (collectively
"Apple Marks") or to any trademark, service mark, logo or trade name
belonging to any Contributor. You agree not to use any Apple Marks in
or as part of the name of products derived from the Original Code or
to endorse or promote products derived from the Original Code other
than as expressly permitted by and in strict compliance at all times
with Apple's third party trademark usage guidelines which are posted
at http://www.apple.com/legal/guidelinesfor3rdparties.html.
11. Ownership. Subject to the licenses granted under this License,
each Contributor retains all rights, title and interest in and to any
Modifications made by such Contributor. Apple retains all rights,
title and interest in and to the Original Code and any Modifications
made by or on behalf of Apple ("Apple Modifications"), and such Apple
Modifications will not be automatically subject to this License. Apple
may, at its sole discretion, choose to license such Apple
Modifications under this License, or on different terms from those
contained in this License or may choose not to license them at all.
12. Termination.
12.1 Termination. This License and the rights granted hereunder will
terminate:
(a) automatically without notice from Apple if You fail to comply with
any term(s) of this License and fail to cure such breach within 30
days of becoming aware of such breach;
(b) immediately in the event of the circumstances described in Section
13.5(b); or
(c) automatically without notice from Apple if You, at any time during
the term of this License, commence an action for patent infringement
against Apple; provided that Apple did not first commence
an action for patent infringement against You in that instance.
12.2 Effect of Termination. Upon termination, You agree to immediately
stop any further use, reproduction, modification, sublicensing and
distribution of the Covered Code. All sublicenses to the Covered Code
which have been properly granted prior to termination shall survive
any termination of this License. Provisions which, by their nature,
should remain in effect beyond the termination of this License shall
survive, including but not limited to Sections 3, 5, 8, 9, 10, 11,
12.2 and 13. No party will be liable to any other for compensation,
indemnity or damages of any sort solely as a result of terminating
this License in accordance with its terms, and termination of this
License will be without prejudice to any other right or remedy of
any party.
13. Miscellaneous.
13.1 Government End Users. The Covered Code is a "commercial item" as
defined in FAR 2.101. Government software and technical data rights in
the Covered Code include only those rights customarily provided to the
public as defined in this License. This customary commercial license
in technical data and software is provided in accordance with FAR
12.211 (Technical Data) and 12.212 (Computer Software) and, for
Department of Defense purchases, DFAR 252.227-7015 (Technical Data --
Commercial Items) and 227.7202-3 (Rights in Commercial Computer
Software or Computer Software Documentation). Accordingly, all U.S.
Government End Users acquire Covered Code with only those rights set
forth herein.
13.2 Relationship of Parties. This License will not be construed as
creating an agency, partnership, joint venture or any other form of
legal association between or among You, Apple or any Contributor, and
You will not represent to the contrary, whether expressly, by
implication, appearance or otherwise.
13.3 Independent Development. Nothing in this License will impair
Apple's right to acquire, license, develop, have others develop for
it, market and/or distribute technology or products that perform the
same or similar functions as, or otherwise compete with,
Modifications, Larger Works, technology or products that You may
develop, produce, market or distribute.
13.4 Waiver; Construction. Failure by Apple or any Contributor to
enforce any provision of this License will not be deemed a waiver of
future enforcement of that or any other provision. Any law or
regulation which provides that the language of a contract shall be
construed against the drafter will not apply to this License.
13.5 Severability. (a) If for any reason a court of competent
jurisdiction finds any provision of this License, or portion thereof,
to be unenforceable, that provision of the License will be enforced to
the maximum extent permissible so as to effect the economic benefits
and intent of the parties, and the remainder of this License will
continue in full force and effect. (b) Notwithstanding the foregoing,
if applicable law prohibits or restricts You from fully and/or
specifically complying with Sections 2 and/or 3 or prevents the
enforceability of either of those Sections, this License will
immediately terminate and You must immediately discontinue any use of
the Covered Code and destroy all copies of it that are in your
possession or control.
13.6 Dispute Resolution. Any litigation or other dispute resolution
between You and Apple relating to this License shall take place in the
Northern District of California, and You and Apple hereby consent to
the personal jurisdiction of, and venue in, the state and federal
courts within that District with respect to this License. The
application of the United Nations Convention on Contracts for the
International Sale of Goods is expressly excluded.
13.7 Entire Agreement; Governing Law. This License constitutes the
entire agreement between the parties with respect to the subject
matter hereof. This License shall be governed by the laws of the
United States and the State of California, except that body of
California law concerning conflicts of law.
Where You are located in the province of Quebec, Canada, the following
clause applies: The parties hereby confirm that they have requested
that this License and all related documents be drafted in English. Les
parties ont exige que le present contrat et tous les documents
connexes soient rediges en anglais.
EXHIBIT A.
"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
Reserved.
This file contains Original Code and/or Modifications of Original Code
as defined in and that are subject to the Apple Public Source License
Version 2.0 (the 'License'). You may not use this file except in
compliance with the License. Please obtain a copy of the License at
http://www.opensource.apple.com/apsl/ and read it before using this
file.
The Original Code and all software distributed under the License are
distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
Please see the License for the specific language governing rights and
limitations under the License."

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,420 @@
/*
* Copyright (c) 2007-2016 by Apple Inc.. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef __AVAILABILITY__
#define __AVAILABILITY__
/*
These macros are for use in OS header files. They enable function prototypes
and Objective-C methods to be tagged with the OS version in which they
were first available; and, if applicable, the OS version in which they
became deprecated.
The desktop Mac OS X and iOS each have different version numbers.
The __OSX_AVAILABLE_STARTING() macro allows you to specify both the desktop
and iOS version numbers. For instance:
__OSX_AVAILABLE_STARTING(__MAC_10_2,__IPHONE_2_0)
means the function/method was first available on Mac OS X 10.2 on the desktop
and first available in iOS 2.0 on the iPhone.
If a function is available on one platform, but not the other a _NA (not
applicable) parameter is used. For instance:
__OSX_AVAILABLE_STARTING(__MAC_10_3,__IPHONE_NA)
means that the function/method was first available on Mac OS X 10.3, and it
currently not implemented on the iPhone.
At some point, a function/method may be deprecated. That means Apple
recommends applications stop using the function, either because there is a
better replacement or the functionality is being phased out. Deprecated
functions/methods can be tagged with a __OSX_AVAILABLE_BUT_DEPRECATED()
macro which specifies the OS version where the function became available
as well as the OS version in which it became deprecated. For instance:
__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_0,__MAC_10_5,__IPHONE_NA,__IPHONE_NA)
means that the function/method was introduced in Mac OS X 10.0, then
became deprecated beginning in Mac OS X 10.5. On iOS the function
has never been available.
For these macros to function properly, a program must specify the OS version range
it is targeting. The min OS version is specified as an option to the compiler:
-mmacosx-version-min=10.x when building for Mac OS X, and -miphoneos-version-min=y.z
when building for the iPhone. The upper bound for the OS version is rarely needed,
but it can be set on the command line via: -D__MAC_OS_X_VERSION_MAX_ALLOWED=10x0 for
Mac OS X and __IPHONE_OS_VERSION_MAX_ALLOWED = y0z00 for iOS.
Examples:
A function available in Mac OS X 10.5 and later, but not on the phone:
extern void mymacfunc() __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_NA);
An Objective-C method in Mac OS X 10.5 and later, but not on the phone:
@interface MyClass : NSObject
-(void) mymacmethod __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_NA);
@end
An enum available on the phone, but not available on Mac OS X:
#if __IPHONE_OS_VERSION_MIN_REQUIRED
enum { myEnum = 1 };
#endif
Note: this works when targeting the Mac OS X platform because
__IPHONE_OS_VERSION_MIN_REQUIRED is undefined which evaluates to zero.
An enum with values added in different iPhoneOS versions:
enum {
myX = 1, // Usable on iPhoneOS 2.1 and later
myY = 2, // Usable on iPhoneOS 3.0 and later
myZ = 3, // Usable on iPhoneOS 3.0 and later
...
Note: you do not want to use #if with enumeration values
when a client needs to see all values at compile time
and use runtime logic to only use the viable values.
It is also possible to use the *_VERSION_MIN_REQUIRED in source code to make one
source base that can be compiled to target a range of OS versions. It is best
to not use the _MAC_* and __IPHONE_* macros for comparisons, but rather their values.
That is because you might get compiled on an old OS that does not define a later
OS version macro, and in the C preprocessor undefined values evaluate to zero
in expresssions, which could cause the #if expression to evaluate in an unexpected
way.
#ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
// code only compiled when targeting Mac OS X and not iPhone
// note use of 1050 instead of __MAC_10_5
#if __MAC_OS_X_VERSION_MIN_REQUIRED < 1050
// code in here might run on pre-Leopard OS
#else
// code here can assume Leopard or later
#endif
#endif
*/
#define __MAC_10_0 1000
#define __MAC_10_1 1010
#define __MAC_10_2 1020
#define __MAC_10_3 1030
#define __MAC_10_4 1040
#define __MAC_10_5 1050
#define __MAC_10_6 1060
#define __MAC_10_7 1070
#define __MAC_10_8 1080
#define __MAC_10_9 1090
#define __MAC_10_10 101000
#define __MAC_10_10_2 101002
#define __MAC_10_10_3 101003
#define __MAC_10_11 101100
#define __MAC_10_11_2 101102
#define __MAC_10_11_3 101103
#define __MAC_10_11_4 101104
#define __MAC_10_12 101200
#define __MAC_10_12_1 101201
#define __MAC_10_12_2 101202
#define __MAC_10_12_4 101204
/* __MAC_NA is not defined to a value but is uses as a token by macros to indicate that the API is unavailable */
#define __IPHONE_2_0 20000
#define __IPHONE_2_1 20100
#define __IPHONE_2_2 20200
#define __IPHONE_3_0 30000
#define __IPHONE_3_1 30100
#define __IPHONE_3_2 30200
#define __IPHONE_4_0 40000
#define __IPHONE_4_1 40100
#define __IPHONE_4_2 40200
#define __IPHONE_4_3 40300
#define __IPHONE_5_0 50000
#define __IPHONE_5_1 50100
#define __IPHONE_6_0 60000
#define __IPHONE_6_1 60100
#define __IPHONE_7_0 70000
#define __IPHONE_7_1 70100
#define __IPHONE_8_0 80000
#define __IPHONE_8_1 80100
#define __IPHONE_8_2 80200
#define __IPHONE_8_3 80300
#define __IPHONE_8_4 80400
#define __IPHONE_9_0 90000
#define __IPHONE_9_1 90100
#define __IPHONE_9_2 90200
#define __IPHONE_9_3 90300
#define __IPHONE_10_0 100000
#define __IPHONE_10_1 100100
#define __IPHONE_10_2 100200
#define __IPHONE_10_3 100300
/* __IPHONE_NA is not defined to a value but is uses as a token by macros to indicate that the API is unavailable */
#define __TVOS_9_0 90000
#define __TVOS_9_1 90100
#define __TVOS_9_2 90200
#define __TVOS_10_0 100000
#define __TVOS_10_0_1 100001
#define __TVOS_10_1 100100
#define __TVOS_10_2 100200
#define __WATCHOS_1_0 10000
#define __WATCHOS_2_0 20000
#define __WATCHOS_3_0 30000
#define __WATCHOS_3_1 30100
#define __WATCHOS_3_1_1 30101
#define __WATCHOS_3_2 30200
#include <AvailabilityInternal.h>
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#define __OSX_AVAILABLE_STARTING(_osx, _ios) __AVAILABILITY_INTERNAL##_ios
#define __OSX_AVAILABLE_BUT_DEPRECATED(_osxIntro, _osxDep, _iosIntro, _iosDep) \
__AVAILABILITY_INTERNAL##_iosIntro##_DEP##_iosDep
#define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg) \
__AVAILABILITY_INTERNAL##_iosIntro##_DEP##_iosDep##_MSG(_msg)
#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
#define __OSX_AVAILABLE_STARTING(_osx, _ios) __AVAILABILITY_INTERNAL##_osx
#define __OSX_AVAILABLE_BUT_DEPRECATED(_osxIntro, _osxDep, _iosIntro, _iosDep) \
__AVAILABILITY_INTERNAL##_osxIntro##_DEP##_osxDep
#define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg) \
__AVAILABILITY_INTERNAL##_osxIntro##_DEP##_osxDep##_MSG(_msg)
#else
#define __OSX_AVAILABLE_STARTING(_osx, _ios)
#define __OSX_AVAILABLE_BUT_DEPRECATED(_osxIntro, _osxDep, _iosIntro, _iosDep)
#define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(_osxIntro, _osxDep, _iosIntro, _iosDep, _msg)
#endif
#if defined(__has_feature)
#if __has_feature(attribute_availability_with_message)
#define __OS_AVAILABILITY(_target, _availability) __attribute__((availability(_target,_availability)))
#define __OS_AVAILABILITY_MSG(_target, _availability, _msg) __attribute__((availability(_target,_availability,message=_msg)))
#elif __has_feature(attribute_availability)
#define __OS_AVAILABILITY(_target, _availability) __attribute__((availability(_target,_availability)))
#define __OS_AVAILABILITY_MSG(_target, _availability, _msg) __attribute__((availability(_target,_availability)))
#else
#define __OS_AVAILABILITY(_target, _availability)
#define __OS_AVAILABILITY_MSG(_target, _availability, _msg)
#endif
#else
#define __OS_AVAILABILITY(_target, _availability)
#define __OS_AVAILABILITY_MSG(_target, _availability, _msg)
#endif
/* for use to document app extension usage */
#if defined(__has_feature)
#if __has_feature(attribute_availability_app_extension)
#define __OSX_EXTENSION_UNAVAILABLE(_msg) __OS_AVAILABILITY_MSG(macosx_app_extension,unavailable,_msg)
#define __IOS_EXTENSION_UNAVAILABLE(_msg) __OS_AVAILABILITY_MSG(ios_app_extension,unavailable,_msg)
#else
#define __OSX_EXTENSION_UNAVAILABLE(_msg)
#define __IOS_EXTENSION_UNAVAILABLE(_msg)
#endif
#else
#define __OSX_EXTENSION_UNAVAILABLE(_msg)
#define __IOS_EXTENSION_UNAVAILABLE(_msg)
#endif
#define __OS_EXTENSION_UNAVAILABLE(_msg) __OSX_EXTENSION_UNAVAILABLE(_msg) __IOS_EXTENSION_UNAVAILABLE(_msg)
/* for use marking APIs available info for Mac OSX */
#if defined(__has_attribute)
#if __has_attribute(availability)
#define __OSX_UNAVAILABLE __OS_AVAILABILITY(macosx,unavailable)
#define __OSX_AVAILABLE(_vers) __OS_AVAILABILITY(macosx,introduced=_vers)
#define __OSX_DEPRECATED(_start, _dep, _msg) __OSX_AVAILABLE(_start) __OS_AVAILABILITY_MSG(macosx,deprecated=_dep,_msg)
#endif
#endif
#ifndef __OSX_UNAVAILABLE
#define __OSX_UNAVAILABLE
#endif
#ifndef __OSX_AVAILABLE
#define __OSX_AVAILABLE(_vers)
#endif
#ifndef __OSX_DEPRECATED
#define __OSX_DEPRECATED(_start, _dep, _msg)
#endif
/* for use marking APIs available info for iOS */
#if defined(__has_attribute)
#if __has_attribute(availability)
#define __IOS_UNAVAILABLE __OS_AVAILABILITY(ios,unavailable)
#define __IOS_PROHIBITED __OS_AVAILABILITY(ios,unavailable)
#define __IOS_AVAILABLE(_vers) __OS_AVAILABILITY(ios,introduced=_vers)
#define __IOS_DEPRECATED(_start, _dep, _msg) __IOS_AVAILABLE(_start) __OS_AVAILABILITY_MSG(ios,deprecated=_dep,_msg)
#endif
#endif
#ifndef __IOS_UNAVAILABLE
#define __IOS_UNAVAILABLE
#endif
#ifndef __IOS_PROHIBITED
#define __IOS_PROHIBITED
#endif
#ifndef __IOS_AVAILABLE
#define __IOS_AVAILABLE(_vers)
#endif
#ifndef __IOS_DEPRECATED
#define __IOS_DEPRECATED(_start, _dep, _msg)
#endif
/* for use marking APIs available info for tvOS */
#if defined(__has_feature)
#if __has_feature(attribute_availability_tvos)
#define __TVOS_UNAVAILABLE __OS_AVAILABILITY(tvos,unavailable)
#define __TVOS_PROHIBITED __OS_AVAILABILITY(tvos,unavailable)
#define __TVOS_AVAILABLE(_vers) __OS_AVAILABILITY(tvos,introduced=_vers)
#define __TVOS_DEPRECATED(_start, _dep, _msg) __TVOS_AVAILABLE(_start) __OS_AVAILABILITY_MSG(tvos,deprecated=_dep,_msg)
#endif
#endif
#ifndef __TVOS_UNAVAILABLE
#define __TVOS_UNAVAILABLE
#endif
#ifndef __TVOS_PROHIBITED
#define __TVOS_PROHIBITED
#endif
#ifndef __TVOS_AVAILABLE
#define __TVOS_AVAILABLE(_vers)
#endif
#ifndef __TVOS_DEPRECATED
#define __TVOS_DEPRECATED(_start, _dep, _msg)
#endif
/* for use marking APIs available info for Watch OS */
#if defined(__has_feature)
#if __has_feature(attribute_availability_watchos)
#define __WATCHOS_UNAVAILABLE __OS_AVAILABILITY(watchos,unavailable)
#define __WATCHOS_PROHIBITED __OS_AVAILABILITY(watchos,unavailable)
#define __WATCHOS_AVAILABLE(_vers) __OS_AVAILABILITY(watchos,introduced=_vers)
#define __WATCHOS_DEPRECATED(_start, _dep, _msg) __WATCHOS_AVAILABLE(_start) __OS_AVAILABILITY_MSG(watchos,deprecated=_dep,_msg)
#endif
#endif
#ifndef __WATCHOS_UNAVAILABLE
#define __WATCHOS_UNAVAILABLE
#endif
#ifndef __WATCHOS_PROHIBITED
#define __WATCHOS_PROHIBITED
#endif
#ifndef __WATCHOS_AVAILABLE
#define __WATCHOS_AVAILABLE(_vers)
#endif
#ifndef __WATCHOS_DEPRECATED
#define __WATCHOS_DEPRECATED(_start, _dep, _msg)
#endif
/* for use marking APIs unavailable for swift */
#if defined(__has_feature)
#if __has_feature(attribute_availability_swift)
#define __SWIFT_UNAVAILABLE __OS_AVAILABILITY(swift,unavailable)
#define __SWIFT_UNAVAILABLE_MSG(_msg) __OS_AVAILABILITY_MSG(swift,unavailable,_msg)
#endif
#endif
#ifndef __SWIFT_UNAVAILABLE
#define __SWIFT_UNAVAILABLE
#endif
#ifndef __SWIFT_UNAVAILABLE_MSG
#define __SWIFT_UNAVAILABLE_MSG(_msg)
#endif
#if __has_include(<AvailabilityProhibitedInternal.h>)
#include <AvailabilityProhibitedInternal.h>
#endif
/*
Macros for defining which versions/platform a given symbol can be used.
@see http://clang.llvm.org/docs/AttributeReference.html#availability
*/
/*
* API Introductions
*
* Use to specify the release that a particular API became available.
*
* Platform names:
* macos, ios, tvos, watchos
*
* Examples:
* __API_AVAILABLE(macos(10.10))
* __API_AVAILABLE(macos(10.9), ios(10.0))
* __API_AVAILABLE(macos(10.4), ios(8.0), watchos(2.0), tvos(10.0))
*/
#define __API_AVAILABLE(...) __API_AVAILABLE_GET_MACRO(__VA_ARGS__,__API_AVAILABLE4, __API_AVAILABLE3, __API_AVAILABLE2, __API_AVAILABLE1)(__VA_ARGS__)
/*
* API Deprecations
*
* Use to specify the release that a particular API became unavailable.
*
* Platform names:
* macos, ios, tvos, watchos
*
* Examples:
*
* __API_DEPRECATED("No longer supported", macos(10.4, 10.8))
* __API_DEPRECATED("No longer supported", macos(10.4, 10.8), ios(2.0, 3.0), watchos(2.0, 3.0), tvos(9.0, 10.0))
*
* __API_DEPRECATED_WITH_REPLACEMENT("-setName:", tvos(10.0, 10.4), ios(9.0, 10.0))
* __API_DEPRECATED_WITH_REPLACEMENT("SomeClassName", macos(10.4, 10.6), watchos(2.0, 3.0))
*/
#define __API_DEPRECATED(...) __API_DEPRECATED_MSG_GET_MACRO(__VA_ARGS__,__API_DEPRECATED_MSG5,__API_DEPRECATED_MSG4,__API_DEPRECATED_MSG3,__API_DEPRECATED_MSG2,__API_DEPRECATED_MSG1)(__VA_ARGS__)
#define __API_DEPRECATED_WITH_REPLACEMENT(...) __API_DEPRECATED_REP_GET_MACRO(__VA_ARGS__,__API_DEPRECATED_REP5,__API_DEPRECATED_REP4,__API_DEPRECATED_REP3,__API_DEPRECATED_REP2,__API_DEPRECATED_REP1)(__VA_ARGS__)
/*
* API Unavailability
* Use to specify that an API is unavailable for a particular platform.
*
* Example:
* __API_UNAVAILABLE(macos)
* __API_UNAVAILABLE(watchos, tvos)
*/
#define __API_UNAVAILABLE(...) __API_UNAVAILABLE_GET_MACRO(__VA_ARGS__,__API_UNAVAILABLE3,__API_UNAVAILABLE2,__API_UNAVAILABLE1)(__VA_ARGS__)
#endif /* __AVAILABILITY__ */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,94 @@
/*!
* @header
* Umbrella header for CoreEntitlements
*/
#ifndef CORE_ENTITLEMENTS_H
#define CORE_ENTITLEMENTS_H
#ifdef __cplusplus
extern "C" {
#endif
typedef const struct CERuntime* CERuntime_t;
typedef struct CEQueryContext* CEQueryContext_t;
#define _CE_INDIRECT 1
#ifdef TXM
#include <attributes.h>
#include <ptrcheck.h>
#endif
#if defined(__has_feature) && __has_feature(bounds_attributes)
#define CE_HEADER_INDEXABLE __attribute__((__indexable__))
#else
#define CE_HEADER_INDEXABLE
#endif
#include <os/base.h>
#include <CoreEntitlements/Errors.h>
#include <CoreEntitlements/Result.h>
#include <CoreEntitlements/Runtime.h>
#include <CoreEntitlements/Entitlements.h>
#include <CoreEntitlements/Serialization.h>
#include <CoreEntitlements/Index.h>
__ptrcheck_abi_assume_single();
/*!
* @typedef CEType_t
* @brief Represents a type of element supported by CoreEntitlements
*
* @const kCETypeUnknown
* An unknown type
*
* @const kCETypeDictionary
* A dictionary container
*
* @const kCETypeSequence
* An ordered sequence container
*
* @const kCETypeInteger
* An integer.
*
* @const kCETypeString
* A string of bytes.
*
* @const kCETypeBool
* A boolean.
*/
OS_CLOSED_ENUM(CEType, uint32_t,
kCETypeUnknown = 0,
kCETypeDictionary = 1,
kCETypeSequence = 2,
kCETypeInteger = 3,
kCETypeString = 4,
kCETypeBool = 5,
kCETypeData = 6);
/*!
* @function CE_RT_LOG
* Log a single message via the current runtime
* Only called if the runtime supports logging.
*/
#define CE_RT_LOG(msg) do { if (rt->log) { rt->log(rt, "[%s]: %s\n", __FUNCTION__, msg); } } while(0)
/*!
* @function CE_RT_LOGF
* Logs using the passed in format. Printf like.
* Only called if the runtime supports logging.
*/
#define CE_RT_LOGF(fmt, ...) do { if (rt->log) { rt->log(rt, "[%s]: " fmt, __FUNCTION__, __VA_ARGS__); } } while(0)
/*!
* @function CE_RT_ABORT
* Invokes the runtime abort function with a passed in message.
* This function should not return.
*/
#define CE_RT_ABORT(...) do { rt->abort(rt, "[%s]: %s\n", __FUNCTION__, __VA_ARGS__); } while(0)
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,80 @@
//
// CoreEntitlementsPriv.h
// CoreEntitlements
//
#ifndef CORE_ENTITLEMENTS_PRIV_H
#define CORE_ENTITLEMENTS_PRIV_H
#ifdef __cplusplus
extern "C" {
#endif
#include <CoreEntitlements/CoreEntitlements.h>
#include <CoreEntitlements/EntitlementsPriv.h>
#define CE_BRIDGE_STRUCT_VERSION 3
#define CCDER_ENTITLEMENTS (CCDER_SEQUENCE | CCDER_CONSTRUCTED | CCDER_APPLICATION)
__ptrcheck_abi_assume_single();
/*!
* @typedef coreentitlements_t
* Wraps up all the CoreEntitlements functions into a nice bundle to be used in the kernel
*/
typedef struct {
uint64_t version;
typeof(&CEAcquireUnmanagedContext) AcquireUnmanagedContext;
typeof(&CEValidate) Validate;
typeof(&CEContextQuery) ContextQuery;
typeof(&CEConjureContextFromDER) ConjureContextFromDER;
typeof(&der_vm_context_create) der_vm_context_create;
typeof(&der_vm_execute) der_vm_execute;
typeof(&der_vm_iterate) der_vm_iterate;
typeof(&der_vm_context_is_valid) der_vm_context_is_valid;
typeof(&der_vm_CEType_from_context) der_vm_CEType_from_context;
typeof(&der_vm_integer_from_context) der_vm_integer_from_context;
typeof(&der_vm_string_from_context) der_vm_string_from_context;
typeof(&der_vm_bool_from_context) der_vm_bool_from_context;
typeof(kCENoError) kNoError;
typeof(kCEAPIMisuse) kAPIMisuse;
typeof(kCEInvalidArgument) kInvalidArgument;
typeof(kCEAllocationFailed) kAllocationFailed;
typeof(kCEMalformedEntitlements) kMalformedEntitlements;
typeof(kCEQueryCannotBeSatisfied) kQueryCannotBeSatisfied;
#if CE_ACCELERATION_SUPPORTED
typeof(kCENotEligibleForAcceleration) kNotEligibleForAcceleration;
#endif
typeof(&CEGetErrorString) GetErrorString;
typeof(&der_vm_buffer_from_context) der_vm_buffer_from_context;
typeof(&CEContextIsSubset) CEContextIsSubset;
#if CE_ACCELERATION_SUPPORTED
typeof(&CEIndexSizeForContext) IndexSizeForContext;
typeof(&CEBuildIndexForContext) BuildIndexForContext;
typeof(&CEFreeIndexForContext) FreeIndexForContext;
typeof(&CEContextIsAccelerated) ContextIsAccelerated;
#endif
} coreentitlements_t;
#ifdef __BLOCKS__
typedef bool (^iteration_trampoline_t)(der_vm_iteration_context ctx);
bool der_vm_block_trampoline(der_vm_iteration_context ctx);
#endif
/*
These are private for now, they're essentially inverse functions for CESerialize.
*/
CEError_t CESizeDeserialization(CEQueryContext_t ctx, size_t* requiredElements);
CEError_t CEDeserialize(CEQueryContext_t ctx, CESerializedElement_t *__counted_by(elementsLength) elements, size_t elementsLength);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,210 @@
//
// Entitlements.h
// CoreEntitlements
//
//
#ifndef CORE_ENTITLEMENTS_ENTITLEMENTS_H
#define CORE_ENTITLEMENTS_ENTITLEMENTS_H
#ifndef _CE_INDIRECT
#error "Please include <CoreEntitlements/CoreEntitlements.h> instead of this file"
#endif
#include <CoreEntitlements/Result.h>
#include <CoreEntitlements/Runtime.h>
__ptrcheck_abi_assume_single();
/*!
* @enum CEVersion_t
* Represents the various versions supported by CoreEntitlements
*/
OS_ENUM(CEVersion, int64_t,
kCEVersionInvalid = 0,
kCEVersionZero = 1,
kCEVersionOne = 2);
/*!
* @struct CEValidationResult
* Contains the result of the call to CEValidate
*/
typedef struct {
CEVersion_t version;
const uint8_t *__ended_by(blob_end) blob;
const uint8_t * blob_end;
} CEValidationResult;
typedef struct {
bool allow_data_elements;
} CEValidationOptions;
/*!
* @function CEValidate
* Validates if the provided blob conforms to one of the entitlement specification understood by CoreEntitlements
* @param rt
* Active runtime
* @param result
* The validation result will be stored here
* @param blob
* Pointer to the start of the entitlements object
* @param blob_end
* Pointer to one byte past the end of the entitlements object
* @discussion
* This function will return kCENoError if the entitlements are valid
*/
CEError_t CEValidate(const CERuntime_t rt, CEValidationResult* result, const uint8_t *__ended_by(blob_end) blob, const uint8_t* blob_end) __result_use_check;
/*!
* @function CEValidateWithOptions
* Validates if the provided blob conforms to one of the entitlement specification understood by CoreEntitlements
* @param rt
* Active runtime
* @param options
* Options that modify how validation behaves
* @param result
* The validation result will be stored here
* @param blob
* Pointer to the start of the entitlements object
* @param blob_end
* Pointer to one byte past the end of the entitlements object
* @discussion
* This function will return kCENoError if the entitlements are valid
*/
CEError_t CEValidateWithOptions(const CERuntime_t rt, CEValidationOptions* options, CEValidationResult* result, const uint8_t *__ended_by(blob_end) blob, const uint8_t* blob_end) __result_use_check;
/*!
* @function CEAcquireManagedContext
* Creates and returns a managed query context for the validated blob against which you can perform queries
* @param rt
* Active runtime (must support allocation and deallocation)
* @param validationResult
* The validation result returned by CEValidate
* @param ctx
* Pointer to where the context is to be returned
* @note
* The returned managed context must be subsequently released with CEAcquireManagedContext
*/
CEError_t CEAcquireManagedContext(const CERuntime_t rt, CEValidationResult validationResult, CEQueryContext_t* ctx) __result_use_check;
/*!
@discussion
Releases the managed context
*/
CEError_t CEReleaseManagedContext(CEQueryContext_t* ctx);
/*!
* @enum CEQueryOpOpcode_t
* These are all the supported operations by the CoreEntitlements VM
*/
OS_ENUM(CEQueryOpOpcode, int64_t,
kCEOpNoop = 0,
kCEOpSelectKey = 1,
kCEOpSelectIndex = 2,
kCEOpMatchString = 3,
kCEOpMatchStringPrefix = 4,
kCEOpMatchBool = 5,
kCEOpStringValueAllowed = 6,
kCEOpMatchInteger = 7,
kCEOpStringPrefixValueAllowed = 8,
kCEOpSelectKeyWithPrefix = 9,
kCEOpIntegerValueAllowed = 10,
kCEOpMatchType = 11,
kCEOpMatchData = 12,
kCEOpMatchDataValueAllowed = 13,
kCEOpMaxOperation = 14, /* Sentinel value */
kCEOpDynamic = 0x1LL << 62);
/*!
* @typedef CEQueryOperation_t
* Represents an operation within the DERQL interpreter
* The opcode specified _which_ operation to perform, while the parameters specify how to perform it.
* Operations are passed by value and may be safely reused.
*/
typedef struct CEQueryOperation {
CEQueryOpOpcode_t opcode;
union {
CEBuffer dynamicParameter;
CEStaticBuffer stringParameter;
int64_t numericParameter;
} parameters;
} CEQueryOperation_t;
typedef CEQueryOperation_t CEQuery_t[];
extern const CEQueryOperation_t* CESelectKeyOperation;
extern const CEQueryOperation_t* CESelectValueOperation;
/*!
* @typedef CEPrepareOptions_t
* Containts the options you may pass in to CEPrepareQuery.
*/
typedef struct CEPrepareOptions {
/*
If materialize is true dynamic ops are turned into static ones
*/
bool materialize;
/*
Controls if CEPrepareQuery should fail on keys in dynamic operations that are too long
*/
bool failOnOversizedParameters;
} CEPrepareOptions_t;
/*!
* @function CEContextQuery
* Performs a query on the passed in CEQueryContext_t
*
* @param ctx
* The context on which to perform the query
*
* @param query
* The sequence of operations to execute
*
* @param queryLength
* The number of operations in the query
*
* @returns
* This function will return kCENoError if the query is satisfiable, otherwise kCEQueryCannotBeSatisfied.
*
* @note
* As stated previously, the query only succeeds if it is satisfiable by the context, meaning that the operations executed in the passed in order
* leave the VM in the valid state. An invalid state may arise from a variety of situations, like trying to select a value for a key that doesn't exist,
* or a failing string matching operations.
*/
CEError_t CEContextQuery(CEQueryContext_t ctx, const CEQueryOperation_t *__counted_by(queryLength) query, size_t queryLength) __result_use_check;
/*!
* @function CEPrepareQuery
* Prepares the query for execution by materializing dynamic operations if needed
*
* @params options
* Options to control how the query should be prepared
*
* @param query
* The sequence of operations to prepare
*
* @param queryLength
* The number of operations in the query
*/
CEError_t CEPrepareQuery(CEPrepareOptions_t options, CEQueryOperation_t *__counted_by(queryLength) query, size_t queryLength);
/*!
* @function CEContextIsSubset
* Checks if the subset <-> superset relation holds between two context.
* The logic relations used to establish that relation correspond to the normal profile-validation rules.
*
* @param subset
* The context that is meant to a subset
*
* @param superset
* The context that is meant to be a superset
*
* @returns
* This function will return kCENoError if the relation holds, otherwise kCEQueryCannotBeSatisfied.
*/
CEError_t CEContextIsSubset(CEQueryContext_t subset, CEQueryContext_t superset);
#include <CoreEntitlements/QueryHelpers.h>
#endif

View file

@ -0,0 +1,45 @@
//
// EntitlementsPriv.h
// CoreEntitlements
//
#ifndef CORE_ENTITLEMENTS_ENTS_PRIV_H
#define CORE_ENTITLEMENTS_ENTS_PRIV_H
#ifdef __cplusplus
extern "C" {
#endif
#include <CoreEntitlements/Entitlements.h>
#include <CoreEntitlements/der_vm.h>
#ifndef CORE_ENTITLEMENTS_I_KNOW_WHAT_IM_DOING
#error This is a private API, please consult with the Trusted Execution team before using this. Misusing these functions will lead to security issues.
#endif
__ptrcheck_abi_assume_single();
struct CEQueryContext {
der_vm_context_t der_context;
bool managed;
};
CEError_t CEAcquireUnmanagedContext(const CERuntime_t rt, CEValidationResult validationResult, struct CEQueryContext* ctx);
/*!
* @function CEConjureContextFromDER
* @brief Conjures up an object from thin air that you can query. Don't use it.
* @note It does no validation.
*/
struct CEQueryContext CEConjureContextFromDER(der_vm_context_t der_context);
CEQueryOperation_t* CECreateStringOpInplace(CEQueryOperation_t* storage, CEQueryOpOpcode_t op, const char *__counted_by(len) data, size_t len);
CEQueryOperation_t* CECreateNumericOpInplace(CEQueryOperation_t* storage, CEQueryOpOpcode_t op, int64_t param);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,53 @@
//
// Errors.h
// CoreEntitlements
//
//
#ifndef CORE_ENTITLEMENTS_ERRORS_H
#define CORE_ENTITLEMENTS_ERRORS_H
#ifndef _CE_INDIRECT
#error "Please include <CoreEntitlements/CoreEntitlements.h> instead of this file"
#endif
#include <sys/cdefs.h>
__ptrcheck_abi_assume_single();
/*!
* @typedef CEError_t
* A shared error type that is returned by CoreEntitlements APIs
*/
typedef const struct CEError *__single CEError_t;
// Macro to define the error for export;
#define CE_DEF_ERROR(name) extern CEError_t name;
// Returned on successful invocation
CE_DEF_ERROR(kCENoError);
// Returned when the library encounters API misuse
CE_DEF_ERROR(kCEAPIMisuse);
// Returned when an invalid argument has been passed in
CE_DEF_ERROR(kCEInvalidArgument);
// Returned when we expected to have allocated data, but we couldn't
CE_DEF_ERROR(kCEAllocationFailed);
// Returned when the passed in entitlements do not conform to any supported format
CE_DEF_ERROR(kCEMalformedEntitlements);
// Returned when a group of queries does not generate a valid result on the current CEQueryContext
CE_DEF_ERROR(kCEQueryCannotBeSatisfied);
// Returned when a context shouldn't be accelerated
CE_DEF_ERROR(kCENotEligibleForAcceleration);
/*!
* @function CEGetErrorString
* Returns a string that describes the error
*/
const char *__unsafe_indexable CEGetErrorString(CEError_t error);
#endif

View file

@ -0,0 +1,86 @@
//
// Index.h
// CoreEntitlements
//
//
#ifndef CORE_ENTITLEMENTS_INDEX_H
#define CORE_ENTITLEMENTS_INDEX_H
#ifndef _CE_INDIRECT
#error "Please include <CoreEntitlements/CoreEntitlements.h> instead of this file"
#endif
#include <CoreEntitlements/Result.h>
/*
The kernel always supports acceleration
*/
#define CE_ACCELERATION_SUPPORTED 1
/*!
@typedef CEAccelerationElement_t
A single element of the acceleration structure, the contents of this struct are an implementation detail
and are subject to change.
*/
typedef struct CEAccelerationElement {
uint32_t key_offset;
uint32_t key_length;
} CEAccelerationElement_t;
/*!
@struct CEAccelerationContext
Contains data required to accelerate queries, the contents of this struct are an implementation detail
and are subject to change.
*/
struct CEAccelerationContext {
CEAccelerationElement_t * __counted_by(index_count) index;
size_t index_count;
};
/*!
@function CEIndexSizeForContext
Computes an upper bound of memory needed to construct an acceleration index for a particular query context.
@param context
The context for which the calculation should be made
@param size
Contains the required size, in bytes.
@returns an error if the context cannot be accelerated, success otherwise
*/
CEError_t CEIndexSizeForContext(CEQueryContext_t context, size_t* size);
/*!
@function CEBuildIndexForContext
Computes and stores and acceleration index into the passed in context.
Building an index requires runtime support.
@param context
The context for which the index should be computed.
*/
CEError_t CEBuildIndexForContext(CEQueryContext_t context);
/*!
@function CEFreeIndexForContext
Frees an index associated with a query context
@param context
The context for which the index should be freed.
*/
CEError_t CEFreeIndexForContext(CEQueryContext_t context);
/*!
@function CEContextIsAccelerated
Checks if the passed in context supports query acceleration
@param context
The context to check.
*/
bool CEContextIsAccelerated(CEQueryContext_t context);
#endif /* CORE_ENTITLEMENTS_INDEX_H */

View file

@ -0,0 +1,30 @@
//
// KernelUtils.hpp
// CoreEntitlements_kernel
//
//
#ifndef CORE_ENTITLEMENTS_KERNEL_H
#define CORE_ENTITLEMENTS_KERNEL_H
#include <CoreEntitlements/CoreEntitlements.h>
#include <libkern/c++/OSPtr.h>
#include <libkern/c++/OSDictionary.h>
#ifndef CORE_ENTITLEMENTS_I_KNOW_WHAT_IM_DOING
#error This is a private API, please consult with the Trusted Execution team before using this. Misusing these functions will lead to security issues.
#endif
/*!
* @function CEQueryContextToOSDictionary
* Private API, converts a query context into an OSDictionary that can be handed out to legacy users
*/
OSPtr<OSDictionary> CEQueryContextToOSDictionary(CEQueryContext_t entitlements);
/*!
* @function CEQueryContextToOSObject
* Private API, converts a query context into an OSObject that may be returned dynamically
*/
OSPtr<OSObject> CEQueryContextToOSObject(CEQueryContext_t context);
#endif

View file

@ -0,0 +1,224 @@
//
// QueryHelpers.h
// CoreEntitlements
//
#ifndef CORE_ENTITLEMENTS_HELPERS_H
#define CORE_ENTITLEMENTS_HELPERS_H
#include <sys/cdefs.h>
__ptrcheck_abi_assume_single();
/*!
* @function CEDynamic
* Marks an opcode as being dynamic
*
* @param op
* Opcode
*/
#define CEDynamic(op) (CEQueryOpOpcode_t)((op) | kCEOpDynamic)
/*!
* @function CESelectIndex
* Returns an operation that when executed will modify the context such that any subsequent operation is performed on the entitlement object at the specified index
*
* @param index
* The index of the object within a container
*
* @discussion
* Using an index that is past the container's size will result in an invalid context
*/
#define CESelectIndex(index) (CEQueryOperation_t){.opcode = kCEOpSelectIndex, .parameters = {.numericParameter = index}}
/*!
* @function CESelectKey
* Returns an operation that when executed will modify the context such that any subsequent operation is performed on the key of the dictionary pair
* @discussion
* Selecting a key on a non-dictionary-pair object is undefined behavior (i..e. it is implementation defined)
*/
#define CESelectKey() CESelectIndex(0)
/*!
* @function CESelectValue
* Returns an operation that when executed will modify the context such that any subsequent operation is performed on the value of the dictionary pair
* @discussion
* Selecting a value on a non-dictionary-pair object is undefined behavior (i..e. it is implementation defined)
*/
#define CESelectValue() CESelectIndex(1)
/*!
* @function CESelectDictValue
* Returns an operation that when executed will modify the context such that any subsequent operation is performed on the object that corresponds
* to the value pointed to by the specified key
*
* @param key
* The key of the object within a container
*
* @discussion
* Using a key that is not found in the container will result in an invalid context
*/
#define CESelectDictValue(key) (CEQueryOperation_t){.opcode = kCEOpSelectKey, .parameters = {.stringParameter = {.data = key, .length = sizeof(key) - 1}}}
#define CESelectDictValueDynamic(key, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpSelectKey), .parameters = {.dynamicParameter = {.data = key, .length = len}}}
/*!
* @function CEMatchString
* Returns an operation that will return a valid context if and only if the context corresponds to a valid string and matches the string exactly
*
* @param string
* The string to match against (MUST BE A STRING LITERAL)
*
* @discussion
* If a valid context is returned it will be in the same state as the execution context
*/
#define CEMatchString(string) (CEQueryOperation_t){.opcode = kCEOpMatchString, .parameters = {.stringParameter = {.data = string, .length = sizeof(string) - 1}}}
#define CEMatchDynamicString(string, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpMatchString), .parameters = {.dynamicParameter = {.data = string, .length = len}}}
/*!
* @function CEMatchPrefix
* Returns an operation that will return a valid context if and only if the context corresponds to a valid string and it's prefix matched the passed in prefix
*
* @param prefix
* The prefix to match against (MUST BE A STRING LITERAL)
*
* @discussion
* If a valid context is returned it will be in the same state as the execution context
*/
#define CEMatchPrefix(prefix) (CEQueryOperation_t){.opcode = kCEOpMatchStringPrefix, .parameters = {.stringParameter = {.data = prefix, .length = sizeof(prefix) - 1}}}
#define CEMatchDynamicPrefix(prefix, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpMatchStringPrefix), .parameters = {.dynamicParameter = {.data = prefix, .length = len}}}
/*!
* @function CEMatchType
* Returns an operation that will return a valid context if and only if the type selected by the context corresponds to the one passed in.
*
* @param type
* The type to match against
*
* @discussion
* If a valid context is returned it will be in the same state as the execution context
*/
#define CEMatchType(type) (CEQueryOperation_t){.opcode = kCEOpMatchType, .parameters = {.numericParameter = (int64_t)type}}
/*!
* @function CEMatchBool
* Returns an operation that will return a valid context if and only if the context corresponds to a valid boolean and matches the boolean exactly
*
* @param val
* The bool to match against
*
* @discussion
* If a valid context is returned it will be in the same state as the execution context
*/
#define CEMatchBool(val) (CEQueryOperation_t){.opcode = kCEOpMatchBool, .parameters = {.numericParameter = !!val}}
/*!
* @function CEMatchInteger
* Returns an operation that will return a valid context if and only if the context corresponds to a valid integer and matches the integer exactly
*
* @param val
* The integer to match against
*
* @discussion
* If a valid context is returned it will be in the same state as the execution context
*/
#define CEMatchInteger(val) (CEQueryOperation_t){.opcode = kCEOpMatchInteger, .parameters = {.numericParameter = val}}
/*!
* @function CEIsIntegerAllowed
* Returns an operation that will return a valid context if 1) the current context is an integer and allows the integer, or 2) the context is an array of integers that allows the integer
*
* @param integer
* The integer to match against
*
* @discussion
* If a valid context is returned it will be in the same state as the execution context
*/
#define CEIsIntegerAllowed(integer) (CEQueryOperation_t){.opcode = kCEOpIntegerValueAllowed, .parameters = {.numericParameter = integer}}
/*!
* @function CEIsStringAllowed
* Returns an operation that will return a valid context if 1) the current context is a string and allows the string via wildcard rules, or 2) the context is an array of strings that allows the string
*
* @param string
* The string to match against (MUST BE A STRING LITERAL)
*
* @discussion
* If a valid context is returned it will be in the same state as the execution context
*/
#define CEIsStringAllowed(string) (CEQueryOperation_t){.opcode = kCEOpStringValueAllowed, .parameters = {.stringParameter = {.data = string, .length = sizeof(string) - 1}}}
#define CEIsDynamicStringAllowed(string, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpStringValueAllowed), .parameters = {.dynamicParameter = {.data = string, .length = len}}}
/*!
* @function CEIsStringPrefixAllowed
* Returns an operation that will return a valid context if 1) the current context is a string and matches the prefix or 2) has an array that has the matches the prefix
*
* @param string
* The string to match against (MUST BE A STRING LITERAL)
*
* @discussion
* If a valid context is returned it will be in the same state as the execution context
*/
#define CEIsStringPrefixAllowed(string) (CEQueryOperation_t){.opcode = kCEOpStringPrefixValueAllowed, .parameters = {.stringParameter = {.data = string, .length = sizeof(string) - 1}}}
#define CEIsDynamicStringPrefixAllowed(string, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpStringPrefixValueAllowed), .parameters = {.dynamicParameter = {.data = (const uint8_t*)(string), .length = len}}}
/*!
* @function CEMatchData
* Returns an operation that will return a valid context if and only if the context corresponds to valid data and matches the data exactly
*
* @param string
* The data to match against (MUST BE A BYTE ARRAY)
*
* @discussion
* If a valid context is returned it will be in the same state as the execution context
*/
#define CEMatchDynamicData(d, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpMatchData), .parameters = {.dynamicParameter = {.data = d, .length = len}}}
/*!
* @function CEIsDataAllowed
* Returns an operation that will return a valid context if 1) the current context is data and allows the data, or 2) the context is an array of data elements that allows the data
*
* @param string
* The data to match against (MUST BE A BYTE ARRAY)
*
* @discussion
* If a valid context is returned it will be in the same state as the execution context
*/
#define CEIsDynamicDataAllowed(d, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpMatchDataValueAllowed), .parameters = {.dynamicParameter = {.data = d, .length = len}}}
#pragma mark Helpers
/*
Macro magic
*/
#define _SELECT_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N
#define _mc_1(_call, x) _call(x),
#define _mc_2(_call, x, ...) _call(x), _mc_1(_call, __VA_ARGS__)
#define _mc_3(_call, x, ...) _call(x), _mc_2(_call, __VA_ARGS__)
#define _mc_4(_call, x, ...) _call(x), _mc_3(_call, __VA_ARGS__)
#define _mc_5(_call, x, ...) _call(x), _mc_4(_call, __VA_ARGS__)
#define _mc_6(_call, x, ...) _call(x), _mc_5(_call, __VA_ARGS__)
#define _mc_7(_call, x, ...) _call(x), _mc_6(_call, __VA_ARGS__)
#define _mc_8(_call, x, ...) _call(x), _mc_7(_call, __VA_ARGS__)
#define _mc_9(_call, x, ...) _call(x), _mc_8(_call, __VA_ARGS__)
#define _mc_10(_call, x, ...) _call(x), _mc_9(_call, __VA_ARGS__)
#define _MACRO_ITER(macro, ...) _SELECT_NTH_ARG(__VA_ARGS__, _mc_10, _mc_9, _mc_8 _mc_7, _mc_6, _mc_5, _mc_4, _mc_3, _mc_2, _mc_1)(macro, __VA_ARGS__)
/*!
Macro to automatically generate a query path from a list of string sub components
So
@code
CE_SELECT_PATH("hello, "world") will select a key "hello" and then look up "world" in the dictionary stored in the value of "hello"
@endcode
*/
#define CE_SELECT_PATH(...) _MACRO_ITER(CESelectDictValue, __VA_ARGS__)
// Macro for string equals
#define CE_STRING_EQUALS(str) CEMatchString(str)
/*
A macro that checks if the passed in context grants (via an explicit true boolean) the entitlement at the passed in path.
*/
#define CE_CONTEXT_GRANTS_ENTITLEMENT(ctx, ...) (CEContextQuery(ctx, (CEQuery_t){CE_SELECT_PATH(__VA_ARGS__) CEMatchBool(true)}, sizeof((CEQuery_t){CE_SELECT_PATH(__VA_ARGS__) CEMatchBool(true)}) / sizeof(CEQueryOperation_t)) == kCENoError)
#endif

View file

@ -0,0 +1,45 @@
//
// Result.h
// CoreEntitlements
//
#ifndef CORE_ENTITLEMENTS_RESULT_H
#define CORE_ENTITLEMENTS_RESULT_H
#ifndef _CE_INDIRECT
#error "Please include <CoreEntitlements/CoreEntitlements.h> instead of this file"
#endif
#include <sys/cdefs.h>
__ptrcheck_abi_assume_single();
#include <CoreEntitlements/Errors.h>
#include <stdint.h>
/*!
* @function CEErrorPassThrough
* Returns its argument. Convenient breakpoint location for when anything raises an error.
*/
static inline CEError_t CEErrorPassThrough(CEError_t E) {
return E;
}
/*!
* @function CE_CHECK
* Checks if the passed in return value from one of CoreEntitlements function is an error, and if so returns that error in the current function
*/
#define CE_CHECK(ret) do { CEError_t _ce_error = ret; if (_ce_error != kCENoError) {return CEErrorPassThrough(_ce_error);} } while(0)
/*!
* @function CE_THROW
* Macro to "throw" (return) one of the CEErrors
*/
#define CE_THROW(err) return CEErrorPassThrough(err)
/*!
* @function CE_OK
* Returns a true if the passed in value corresponds to kCENoError
*/
#define CE_OK(ret) ((ret) == kCENoError)
#endif

View file

@ -0,0 +1,110 @@
//
// Runtime.h
// CoreEntitlements
//
//
#ifndef CORE_ENTITLEMENTS_RUNTIME_H
#define CORE_ENTITLEMENTS_RUNTIME_H
#ifndef _CE_INDIRECT
#error "Please include <CoreEntitlements/CoreEntitlements.h> instead of this file"
#endif
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
__ptrcheck_abi_assume_single();
#define CE_MAX_KEY_SIZE 240
#ifndef __result_use_check
#define __result_use_check
#endif
#define CE_RUNTIME_VERSION 1
#define CE_RUNTIME_WITH_INDEX_VERSION 2
/*!
* @struct CEBuffer
* Represents a sized chunk of DER data
* Strings and blobs used and returned by CoreEntitlements always use CEBuffer
*
* @note
* If a DER string is returned to you via a CEBuffer, you cannot assume it is null-terminated.
*/
typedef struct {
const uint8_t *__counted_by(length) data;
size_t length;
} CEBuffer;
/*!
* @struct CEStaticBuffer
* Represents a sized chunk of data that is stored inline
*/
typedef struct {
uint8_t data[CE_MAX_KEY_SIZE];
size_t length;
} CEStaticBuffer;
#define CEBuffStr(str) (CEBuffer){.data = (const uint8_t*)str, .length = sizeof(str) - 1}
/*!
* @typedef CERuntimeMalloc
* Function prototype that the CERuntime may ues to allocate data (e.g.. malloc)
*/
typedef void* __unsafe_indexable (*CERuntimeMalloc)(const CERuntime_t rt, size_t size) __result_use_check;
/*!
* @typedef CERuntimeFree
* Function prototype that the CERuntime may ues to free allocated data (e.g. free)
*/
typedef void (*CERuntimeFree)(const CERuntime_t rt, void* address);
/*!
* @typedef CERuntimeLog
* Function prototype that the CERuntime may use to log helpful information (e.g. printf)
*/
typedef void (*CERuntimeLog)(const CERuntime_t rt, const char* __unsafe_indexable fmt, ...) __printflike(2, 3);
/*!
* @typedef CERuntimeAbort
* Function prototype that the CERuntime will use if it encounters a condition which may compromise the integrity of the system (e.g. abort, panic)
*/
typedef void (*CERuntimeAbort)(const CERuntime_t rt, const char* __unsafe_indexable fmt, ...) __printflike(2, 3) __attribute__((noreturn));
/*!
* @typedef CERuntimeInternalStatus
* Function prototype that the CERuntime may use to query AppleInternal status
*/
typedef bool (*CERuntimeInternalStatus)(const CERuntime_t rt);
/*!
* @typedef CERuntimeAllocIndex
* Function prototype that the CERuntime may ues to allocate an index of the specified size
*/
typedef void* __unsafe_indexable (*CERuntimeAllocIndex)(const CERuntime_t rt, size_t size) __result_use_check;
/*!
* @typedef CERuntimeFreeIndex
* Function prototype that the CERuntime may ues to free an index of the specified size
*/
typedef void (*CERuntimeFreeIndex)(const CERuntime_t rt, void* index, size_t size);
/*!
* @struct CERuntime
* This structure represents the interface that CoreEntitlements uses to communicate with the outside world.
* The presense or absence of function pointers in this structure may degrade certain functionality.
*
* @note
* The only prototype that MUST be implemented is CERuntimeAbort abort.
*/
struct CERuntime {
const uint64_t version;
const CERuntimeMalloc alloc;
const CERuntimeFree free;
const CERuntimeLog log;
const CERuntimeAbort abort;
const CERuntimeInternalStatus internalStatus;
const CERuntimeAllocIndex allocIndex;
const CERuntimeFreeIndex freeIndex;
} ;
#endif

View file

@ -0,0 +1,181 @@
//
// Serialization.h
// CoreEntitlements
//
//
#ifndef CORE_ENTITLEMENTS_SERIALIZATION_H
#define CORE_ENTITLEMENTS_SERIALIZATION_H
#ifndef _CE_INDIRECT
#error "Please include <CoreEntitlements/CoreEntitlements.h> instead of this file"
#endif
#include <CoreEntitlements/Result.h>
#include <CoreEntitlements/Runtime.h>
#include <CoreEntitlements/Entitlements.h>
__ptrcheck_abi_assume_single();
/*!
* @enum CESerializedElementType_t
* These are the primitive types that CoreEntitlements can serialize
* Depending on the underlying representation some of these elements may be "virtual" or zero-sized.
* However, they must still be included.
*/
OS_CLOSED_ENUM(CESerializedElementType, int64_t,
/* A boolean element with a true / false value */
kCESerializedBool = 1,
/* A string element with a definite length */
kCESerializedString = 2,
/* A key string element with a definite length */
kCESerializedKey = 3,
/* An integer element, must be representable as int64_t */
kCESerializedInteger = 4,
/* Marks the start of an array / ordered sequence */
kCESerializedArrayBegin = 5,
/* Marks the end of an array / ordered sequence */
kCESerializedArrayEnd = 6,
/* Marks the start of a dictionary */
/* The only valid elements contained in a dictionary are tuples (represented as an ordered sequence) */
/* The first element of the ordered sequence must be kCESerializedString value */
/* No restrictions are placed on the contents of the second element*/
kCESerializedDictionaryBegin = 7,
/* Marks the end of a dictionary */
kCESerializedDictionaryEnd = 8,
/* A data element with a definite length*/
kCESerializedData = 9,
);
/*!
* @typedef CESerializedElement_t
* This structure represents an encodable piece of data, along with its type and length (in bytes).
* For the most part you will not need to use this structure manually, and instead you should use the helpers below
*/
typedef struct CESerializedElement {
CESerializedElementType_t type;
union {
#if !__has_ptrcheck
void* bytes;
#endif
int64_t value;
} data;
size_t length;
bool pair;
} CESerializedElement_t;
static inline void *CE_HEADER_INDEXABLE CESerializedElementGetData(const CESerializedElement_t *element) {
return __unsafe_forge_bidi_indexable(void *, element->data.value, element->length);
}
static inline void CESerializedElementSetData(CESerializedElement_t *element, void *__sized_by(length) bytes, size_t length) {
element->data.value = (intptr_t)bytes;
element->length = length;
}
/*!
* @function CESizeSerialization
* This function will iterate over the elements that are to be serialized and compute the size of an allocation that needs to be made
* for a successful serialization.
*
* @note
* This function may modify the length field of the CESerializedElements that are passed in. This must be done for serialization to succeed
*
* @returns
* kCENoError if the requiredSize has been successfully populated and contains a valid value
*/
CEError_t CESizeSerialization(CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, size_t* requiredSize) __result_use_check;
/*!
* @function CESizeXMLSerialization
* This function will iterate over the elements that are to be serialized and compute the size of an allocation that needs to be made
* for a successful serialization to XML.
*
* @note
* This function may modify the length field of the CESerializedElements that are passed in. This must be done for serialization to succeed
*
* @returns
* kCENoError if the requiredSize has been successfully populated and contains a valid value
*/
CEError_t CESizeXMLSerialization(CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, size_t* requiredSize) __result_use_check;
/*!
* @function CESerializeWithOptions
* Serializes the array of elements that contains the underlying data. The elements must have been sized with CESizeSerialization before calling this function.
*
* @param runtime
* The runtime to use for this operation
*
* @param options
* Options that modify what can be serialized.
*
* @param elements
* The list of elements to serialize
*
* @param elementsCount
* How many elements are in that list
*
* @param start
* A pointer to the first byte into a buffer that will be filled with the serialized representation
*
* @param end
* A pointer 1 byte past the end of the buffer to be used for serialization
*/
CEError_t CESerializeWithOptions(const CERuntime_t runtime, CEValidationOptions* options, CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, uint8_t *__ended_by(end) start, uint8_t* end) __result_use_check;
/*!
* @function CESerialize
* Serializes the array of elements that contains the underlying data. The elements must have been sized with CESizeSerialization before calling this function.
*
* @param runtime
* The runtime to use for this operation
*
* @param elements
* The list of elements to serialize
*
* @param elementsCount
* How many elements are in that list
*
* @param start
* A pointer to the first byte into a buffer that will be filled with the serialized representation
*
* @param end
* A pointer 1 byte past the end of the buffer to be used for serialization
*/
CEError_t CESerialize(const CERuntime_t runtime, CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, uint8_t *__ended_by(end) start, uint8_t* end) __result_use_check;
/*!
* @function CESerializeXML
* Serializes the array of elements that contains the underlying data. The elements must have been sized with CESizeXMLSerialization before calling this function.
*
* @param runtime
* The runtime to use for this operation
*
* @param elements
* The list of elements to serialize
*
* @param elementsCount
* How many elements are in that list
*
* @param start
* A pointer to the first byte into a buffer that will be filled with the serialized representation
*
* @param end
* A pointer 1 byte past the end of the buffer to be used for serialization
*/
CEError_t CESerializeXML(const CERuntime_t runtime, CESerializedElement_t elements[__counted_by(elementsCount)], size_t elementsCount, uint8_t *__ended_by(end) start, uint8_t* end) __result_use_check;
// Helpers
// These automatically construct CESerializedElements for you
#define CESerializeInteger(intv) (CESerializedElement_t){.type = kCESerializedInteger, .data.value = intv}
#define CESerializeBool(boolVal) (CESerializedElement_t){.type = kCESerializedBool, .data.value = !!boolVal}
#define CESerializeStaticString(strVal) (CESerializedElement_t){.type = kCESerializedString, .data.value = (intptr_t)strVal, .length = sizeof(strVal) - 1}
#define CESerializeKey(strVal) (CESerializedElement_t){.type = kCESerializedKey, .data.value = (intptr_t)strVal, .length = sizeof(strVal) - 1}
#define CESerializeDynamicKey(strVal, len) (CESerializedElement_t){.type = kCESerializedKey, .data.value = (intptr_t)strVal, .length = len}
#define CESerializeString(strVal, len) (CESerializedElement_t){.type = kCESerializedString, .data.value = (intptr_t)strVal, .length = len}
#define CESerializeData(dataVal, len) (CESerializedElement_t){.type = kCESerializedData, .data.value = (intptr_t)dataVal, .length = len}
#define CESerializeArray(...) (CESerializedElement_t){.type = kCESerializedArrayBegin}, __VA_ARGS__ , (CESerializedElement_t){.type = kCESerializedArrayEnd}
#define CESerializeDictionary(...) (CESerializedElement_t){.type = kCESerializedDictionaryBegin}, __VA_ARGS__ , (CESerializedElement_t){.type = kCESerializedDictionaryEnd}
#define CESerializeDictionaryPair(a, b) CESerializeArray(a, b)
#endif

View file

@ -0,0 +1,271 @@
//
// der_vm.h
// CoreEntitlements
//
#ifndef CORE_ENTITLEMENTS_DER_VM_H
#define CORE_ENTITLEMENTS_DER_VM_H
#include <CoreEntitlements/CoreEntitlements.h>
#include <stdint.h>
#include <stdbool.h>
__ptrcheck_abi_assume_single();
// The kernel doesn't have access to this one
#if __has_include (<corecrypto/ccder.h>)
#include <corecrypto/ccder.h>
#else
typedef unsigned long ccder_tag;
#endif
/*!
* @typedef der_vm_context_t
* Represents the current execution state of the DERQL interpreter.
* The context can be initialized with der_vm_context_create and subsequently used in invocations of der_vm_execute.
* This object is passed by value and the functions that operate on the der_vm_context_t do not modify it but instead return a copy.
* As a consequence, the state of the interpreter can be captured at any execution point by holding on to the context.
*/
typedef struct der_vm_context {
CERuntime_t runtime;
#if CE_ACCELERATION_SUPPORTED
struct CEAccelerationContext lookup;
#endif
ccder_tag dictionary_tag;
bool sorted;
bool valid;
union {
// the one you should use
ccder_read_blob ccstate;
// for compatibility
struct {
const uint8_t *__ended_by(der_end) der_start;
const uint8_t *der_end;
} state;
};
} der_vm_context_t;
/*!
* @function der_vm_context_create
* Returns an initialized, valid, der_vm_context_t against which query operations may be performed
* @param rt
* Active runtime
* @param dictionary_tag
* Which DER tag should be used when matching dictionaries
* @param sorted_keys
* Whether the VM can assume that the keys are sorted
* @param der
* Pointer to the start of a DER object
* @param der_end
* Pointer to one byte past the end of the DER object
* @discussion
* The caller must ensure that the memory pointed to by der remains valid as long as the der_vm_context_t is used.
* The caller must ensure that the DER object has been validated.
*/
der_vm_context_t der_vm_context_create(const CERuntime_t rt, ccder_tag dictionary_tag, bool sorted_keys, const uint8_t *__ended_by(der_end) der, const uint8_t *der_end);
/*!
* @function der_vm_execute
* Returns a new context that is derived by applying the op to the passed in context
*
* @param context
* Context to execute against
*
* @param op
* An operation to be performed against the context
* This op should be created by one of the CEMatch* or CESelect* functions
*
* @discussion
* If the VM encounters:
* 1. Invalid operation
* 2. An operation that fails to execute
* 3. Invalid state
* The VM will attempt to return an invalid context.
* If the VM encounters an operation that it does not understand, the runtime's abort function will be executed.
*/
der_vm_context_t der_vm_execute(const der_vm_context_t context, CEQueryOperation_t op);
/*!
* @function der_vm_execute_nocopy
* Returns a new context that is derived by applying the op to the passed in context
*
* @param context
* Context to execute against
*
* @param op
* An operation to be performed against the context
* This op should be created by one of the CEMatch* or CESelect* functions
* The operation may be modified after execution and should not be re-used
*
* @discussion
* If the VM encounters:
* 1. Invalid operation
* 2. An operation that fails to execute
* 3. Invalid state
* The VM will attempt to return an invalid context.
* If the VM encounters an operation that it does not understand, the runtime's abort function will be executed.
*/
der_vm_context_t der_vm_execute_nocopy(const der_vm_context_t context, const CEQueryOperation_t* op);
/*!
* @function der_vm_execute_seq_nocopy
* Returns a new context that is derived by applying the operation sequence to the passed in context
*
* @param context
* Context to execute against
*
* @param query
* Operations to be performed against the context, see der_vm_execute_nocopy for more
*
* @param queryLength
* Number of operations in the query
*
*/
der_vm_context_t der_vm_execute_seq_nocopy(const der_vm_context_t context, const CEQueryOperation_t *__counted_by(queryLength) query, size_t queryLength);
/*!
* @typedef der_vm_iteration_context
* Iteration context that gets passed in on every call
*
* @field original
* The original DER VM context (the container over which we are iterating)
*
* @field active
* The actively selected DER VM context (i.e. the value)
*
* @field parent_type
* The type of object being iterated over (dictionary or array)
*
* @field active_type
* The type of the selected object
*
* @field user_data
* The object you passed in the call to der_vm_iterate
*/
typedef struct {
der_vm_context_t original;
der_vm_context_t active;
CEType_t parent_type;
CEType_t active_type;
void* user_data;
} der_vm_iteration_context;
/*!
* @typedef der_vm_iteration_callback
*
* @brief Function definition for the callback that der_vm_iterate uses
*
* @param ctx The information about the iterable is stored here
*/
typedef bool (*der_vm_iteration_callback)(der_vm_iteration_context ctx);
/*!
* @function der_vm_iterate
* @brief Iterates over a DER container, caliing the callback for every element
*
* @param context The context that points to a container
* @param user_data This will be passed in verbatim in the der_vm_iteration_context
* @param callback This function is called for every element
*
* @returns kCENoError if the function exited normally
*/
CEError_t der_vm_iterate(const der_vm_context_t context, void* user_data, der_vm_iteration_callback callback);
#ifdef __BLOCKS__
/*!
* @typedef der_vm_iteration_block
*
* @brief Function definition for the callback that der_vm_iterate_b uses
*
* @param ctx The information about the iterable is stored here, you may modify it
*/
typedef bool (^der_vm_iteration_block)(der_vm_iteration_context* ctx);
/*!
* @function der_vm_iterate_b
* @brief Iterates over a DER container, calling the block for every element
* @note dev_vm_iterate is implemented using the block interface. Using this function directly is more efficient.
* @param context The context that points to a container
* @param callback This block is called for every element
*
* @returns kCENoError if the function exited normally
*/
CEError_t der_vm_iterate_b(const der_vm_context_t* context, der_vm_iteration_block callback);
#endif
/*!
* @function der_vm_context_is_valid
* Returns a boolean indication if a particular context is valid
*
* @param context
* The context in question
*
* @discussion
* It is generally safe to execute any operation against an invalid context
* However the resulting context will also be invalid
*/
bool der_vm_context_is_valid(const der_vm_context_t context);
/*!
* @function der_vm_CEType_from_context
* Returns a CEType_t corresponding to the item currently pointed to by the context's DER state
*
* @param context
* The context in question
* @param tag
* Nullable pointer to where to store the decoded DER tag
*/
CEType_t der_vm_CEType_from_context(const der_vm_context_t context, ccder_tag* tag);
/*!
* @function der_vm_CEType_from_ccder_tag
* Returns a CEType_t corresponding to the tag value, without touching the context's DER state
*
* @param context
* The context in question
* @param tag
* Nullable pointer to where to store the decoded DER tag
*/
CEType_t der_vm_CEType_from_ccder_tag(const der_vm_context_t context, ccder_tag tag);
/*!
* @function der_vm_integer_from_context
* Returns the number selected by the current context
*/
int64_t der_vm_integer_from_context(const der_vm_context_t context);
/*!
* @function der_vm_string_from_context
* Returns the string selected by the current context
*/
CEBuffer der_vm_string_from_context(const der_vm_context_t context);
/*!
* @function der_vm_bool_from_context
* Returns the bool selected by the current context
*/
bool der_vm_bool_from_context(const der_vm_context_t context);
/*!
* @function der_vm_data_from_context
* Returns the data selected by the current context
*/
CEBuffer der_vm_data_from_context(const der_vm_context_t context);
/*!
* @function der_vm_buffer_from_context
* Returns the content described by the tag in the context
*/
CEBuffer der_vm_buffer_from_context(const der_vm_context_t context);
/*!
* @function CEBuffer_cmp
* Does a memcmp like match between two CEBuffers
*/
int CEBuffer_cmp(const CEBuffer left, const CEBuffer right);
#endif

View file

@ -0,0 +1,68 @@
//
// CTConfig.h
// CoreTrust
//
// Copyright © 2021 Apple. All rights reserved.
//
#ifndef _CORETRUST_CONFIG_H_
#define _CORETRUST_CONFIG_H_
#if EFI
// This requires $(SDKROOT)/usr/local/efi/include/Platform to be in your header
// search path.
#include <Apple/Common/Library/Include/EfiCompatibility.h>
#else // !EFI
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#endif // !EFI
/* Bounds attributes */
#if __has_include(<ptrcheck.h>)
#include <ptrcheck.h>
#else
#define __single
#define __unsafe_indexable
#define __counted_by(N)
#define __sized_by(N)
#define __ended_by(E)
#define __ptrcheck_abi_assume_single()
#define __ptrcheck_abi_assume_unsafe_indexable()
#define __unsafe_forge_bidi_indexable(T, P, S) ((T)(P))
#define __unsafe_forge_single(T, P) ((T)(P))
#endif
#if EFI
#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
#else // !EFI
#include <sys/cdefs.h>
#endif // !EFI
__BEGIN_DECLS
#if EFI
typedef UINT8 CT_uint8_t;
typedef UINT32 CT_uint32_t;
typedef INT32 CT_int;
typedef UINT64 CT_uint64_t;
typedef size_t CT_size_t;
typedef BOOLEAN CT_bool;
#else // !EFI
typedef uint8_t CT_uint8_t;
typedef uint32_t CT_uint32_t;
typedef uint64_t CT_uint64_t;
typedef size_t CT_size_t;
typedef int CT_int;
typedef bool CT_bool;
#endif // !EFI
__END_DECLS
#endif /* _CORETRUST_CONFIG_H_ */

View file

@ -0,0 +1,656 @@
//
// CoreTrust.h
// CoreTrust
//
// Copyright © 2017-2020 Apple Inc. All rights reserved.
//
#ifndef _CORETRUST_EVALUATE_H_
#define _CORETRUST_EVALUATE_H_
#include "CTConfig.h"
__BEGIN_DECLS
__ptrcheck_abi_assume_single()
typedef struct x509_octet_string {
const CT_uint8_t * __counted_by(length) data;
CT_size_t length;
} CTAsn1Item;
extern const CTAsn1Item CTOidItemAppleImg4Manifest; //1.2.840.113635.100.6.1.15
extern const CTAsn1Item CTOidItemAppleDeviceAttestationNonce; // 1.2.840.113635.100.8.2
extern const CTAsn1Item CTOidItemAppleDeviceAttestationHardwareProperties; // 1.2.840.113635.100.8.4
extern const CTAsn1Item CTOidItemAppleDeviceAttestationKeyUsageProperties; // 1.2.840.113635.100.8.5
extern const CTAsn1Item CTOidItemAppleDeviceAttestationDeviceOSInformation; // 1.2.840.113635.100.8.7
/*! @function CTParseCertificateSet
@abstract Parses binary (DER-encoded) certificates concatenated in memory into parsed CTAsn1Items
@param der pointer to beginning of the encoded certificates
@param der_end pointer to end of the encoded certificates
@param certStorage an allocated array of CTAsn1Items which will be populated by the parser
@param certStorageLen the number of CTAsn1Item in certStorage
@param numParsedCerts return value, the number of certs successfully parse from the input
@return 0 upon success or a parsing error (see CTErrors.h) */
CT_int CTParseCertificateSet(
const CT_uint8_t * __ended_by(der_end) der,
const CT_uint8_t *der_end,
CTAsn1Item * __counted_by(certStorageLen) certStorage,
CT_size_t certStorageLen,
CT_size_t *numParsedCerts);
/*! @function CTParseExtensionValue
@abstract Parse a certificate and return the value of an extension with a specifed extnId
@param certData pointer to beginning of the encoded certificate
@param certLen the length of the certificate
@param extensionOidData pointer to the extnId OID to find in the certificate
@param extensionOidLen length of the OID
@param extensionValueData return value, pointer to the extension value found in the certificate with the specified OID
@param extensionValueLen return value, length of the extension value found
@return 0 upon success, a parsing error (see CTErrors.h) */
CT_int CTParseExtensionValue(
const CT_uint8_t * __counted_by(certLen) certData,
CT_size_t certLen,
const CT_uint8_t *__counted_by(extensionOidLen) extensionOidData,
CT_size_t extensionOidLen,
const CT_uint8_t * __counted_by(*extensionValueLen) *extensionValueData,
CT_size_t *extensionValueLen);
/*! @function CTParseKey
@abstract Parse a certificate and return the public key
@param certData pointer to beginning of the encoded certificate
@param certLen the length of the certificate
@param keyData return value, pointer to the key in the parsed certificate
@param keyLen return value, length of the key in the parsed certificate
@return 0 upon success, a parsing error (see CTErrors.h) */
CT_int CTParseKey(
const CT_uint8_t * __counted_by(certLen) certData,
CT_size_t certLen,
const CT_uint8_t *__counted_by(*keyLen) *keyData,
CT_size_t *keyLen);
/*! @function CTEvaluateSavageCerts
@abstract Verify certificates against Savage policy, with specified anchor key
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param rootKeyData pointer to the anchor public key
@param rootKeyLen length of the anchor public key
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@param isProdCert return value, boolean indicating whether the leaf certificate is prod-issued
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateSavageCerts(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(rootKeyLen) rootKeyData, CT_size_t rootKeyLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen,
CT_bool *isProdCert);
/*! @function CTEvaluateSavageCertsWithUID
@abstract Verify certificates against Savage policy, with specified anchor key
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param rootKeyData pointer to the anchor public key
@param rootKeyLen length of the anchor public key
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@param UIDData pointer to a preallocated buffer of UIDLen, which will be populated with the UID
@param UIDLen length of the UIDData buffer
@param isProdCert return value, boolean indicating whether the leaf certificate is prod-issued
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateSavageCertsWithUID(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(rootKeyLen) rootKeyData, CT_size_t rootKeyLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen,
CT_uint8_t *__counted_by(UIDLen) UIDData, CT_size_t UIDLen,
CT_bool *isProdCert);
/*! @function CTEvaluateYonkersCerts
@abstract Verify certificates against Yonkers policy, with specified anchor key
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param rootKeyData pointer to the anchor public key
@param rootKeyLen length of the anchor public key
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@param UIDData pointer to a preallocated buffer of UIDLen, which will be populated with the UID
@param UIDLen length of the UIDData buffer
@param isProdCert return value, boolean indicating whether the leaf certificate is prod-issued
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateYonkersCerts(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(rootKeyLen) rootKeyData, CT_size_t rootKeyLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen,
CT_uint8_t *__counted_by(UIDLen) UIDData, CT_size_t UIDLen,
CT_bool *isProdCert);
/*! @function CTEvaluateSensorCerts
@abstract Verify certificates against Sensor(s) policy, with specified anchor key and intermediate marker value
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param rootKeyData pointer to the anchor public key
@param rootKeyLen length of the anchor public key
@param intermediateMarker pointer to the value expected in the intermediate marker extension
@param intermediateMarkerLen length of the intermediate marker value
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@param UIDData pointer to a preallocated buffer of UIDLen, which will be populated with the UID
@param UIDLen length of the UIDData buffer
@param isProdCert return value, boolean indicating whether the leaf certificate is prod-issued
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateSensorCerts(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(rootKeyLen) rootKeyData, CT_size_t rootKeyLen,
const CT_uint8_t *__counted_by(intermediateMarkerLen) intermediateMarker, CT_size_t intermediateMarkerLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen,
CT_uint8_t *__counted_by(UIDLen) UIDData, CT_size_t UIDLen,
CT_bool *isProdCert);
/*! @function CTEvaluateAcrt
@abstract Verify certificates against acrt policy
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateAcrt(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen);
/*! @function CTEvaluateUcrt
@abstract Verify certificates against ucrt policy
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateUcrt(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen); // Output: points to the leaf key data in the input certsData)
/*! @function CTEvaluateUcrtTestRoot
@abstract Verify certificates against ucrt policy, with optional anchor key for test roots
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param rootKeyData optional pointer to the test anchor public key. If unspecified the production anchor will be used
@param rootKeyLen length of the optional anchor public key
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateUcrtTestRoot(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(rootKeyLen) rootKeyData, CT_size_t rootKeyLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen);
/*! @function CTEvaluateBAASystem
@abstract Verify certificates against BAA scrt-attested policy
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateBAASystem(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen);
typedef struct baa_identity {
CT_uint32_t chipId;
CT_uint64_t ecid;
CT_bool productionStatus;
CT_bool securityMode;
CT_uint8_t securityDomain;
CTAsn1Item img4;
} CTBAAIdentity;
/*! @function CTEvaluateBAASystemWithId
@abstract Verify certificates against BAA scrt-attested policy, returning BAA identity
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@param identity return value, BAA identity from leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateBAASystemWithId(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen,
CTBAAIdentity *identity);
/*! @function CTEvaluateBAASystemTestRoot
@abstract Verify certificates against BAA scrt-attested policy, returning BAA identity with optional anchor key for test roots
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param rootKeyData optional pointer to the test anchor public key. If unspecified the production anchor will be used
@param rootKeyLen length of the optional anchor public key
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@param identity return value, BAA identity from leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateBAASystemTestRoot(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(rootKeyLen) rootKeyData, CT_size_t rootKeyLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen,
CTBAAIdentity *identity);
/*! @function CTEvaluateBAAUser
@abstract Verify certificates against BAA ucrt-attested policy, returning BAA identity
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@param identity return value, BAA identity from leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateBAAUser(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen,
CTBAAIdentity *identity);
/*! @function CTEvaluateBAAUserTestRoot
@abstract Verify certificates against BAA ucrt-attested policy, returning BAA identity with optional anchor key for test roots
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param rootKeyData optional pointer to the test anchor public key. If unspecified the production anchor will be used
@param rootKeyLen length of the optional anchor public key
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@param identity return value, BAA identity from leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateBAAUserTestRoot(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(rootKeyLen) rootKeyData, CT_size_t rootKeyLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen,
CTBAAIdentity *identity);
/*! @function CTEvaluateBAAAccessory
@abstract Verify certificates against BAA accessory (MFi4) policy
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param rootKeyData optional pointer to the test anchor public key. If unspecified the production anchor will be used
@param rootKeyLen length of the optional anchor public key
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@param propertiesData return value, pointer to the Apple Accessories properties extension value in the verified leaf certificate
@param propertiesLen return value, length of the properties in the verified leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateBAAAccessory(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(rootKeyLen) rootKeyData, CT_size_t rootKeyLen,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen,
const CT_uint8_t *__counted_by(*propertiesLen) *propertiesData, CT_size_t *propertiesLen);
/*! @function CTEvaluateSatori
@abstract Verify certificates against Satori policy
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param allowTestRoot allow the Test Apple roots to be used as anchors in addition to the production roots
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateSatori(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
CT_bool allowTestRoot,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen);
/*! @function CTEvaluatePragueSignatureCMS
@abstract Verify CMS signature and certificates against Prague policy
@param cmsData pointer to beginning of the binary (BER-encoded) CMS object
@param cmsLen the length of the CMS object
@param detachedData pointer to data that is signed by the CMS object
@param detachedDataLen the length of the signed data
@param allowTestRoot allow the Test Apple roots to be used as anchors in addition to the production roots
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluatePragueSignatureCMS(
const CT_uint8_t *__counted_by(cmsLen) cmsData, CT_size_t cmsLen,
const CT_uint8_t *__counted_by(detachedDataLen) detachedData, CT_size_t detachedDataLen,
CT_bool allowTestRoot,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen);
/*! @function CTEvaluateKDLSignatureCMS
@abstract Verify CMS signature and certificates against KDL policy
@param cmsData pointer to beginning of the binary (BER-encoded) CMS object
@param cmsLen the length of the CMS object
@param detachedData pointer to data that is signed by the CMS object
@param detachedDataLen the length of the signed data
@param allowTestRoot allow the Test Apple roots to be used as anchors in addition to the production roots
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateKDLSignatureCMS(
const CT_uint8_t *__counted_by(cmsLen) cmsData, CT_size_t cmsLen, // Input: CMS signature blob
const CT_uint8_t *__counted_by(detachedDataLen) detachedData, CT_size_t detachedDataLen, // Input: data signed by CMS blob
CT_bool allowTestRoot, // Input: permit use of test hierarchy
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen); // Output: points to leaf key data in input cmsData
typedef CT_uint64_t CoreTrustPolicyFlags;
enum {
CORETRUST_POLICY_BASIC = 0,
CORETRUST_POLICY_SAVAGE_DEV = 1 << 0,
CORETRUST_POLICY_SAVAGE_PROD = 1 << 1,
CORETRUST_POLICY_MFI_AUTHV3 = 1 << 2,
CORETRUST_POLICY_MAC_PLATFORM = 1 << 3,
CORETRUST_POLICY_MAC_DEVELOPER = 1 << 4,
CORETRUST_POLICY_DEVELOPER_ID = 1 << 5,
CORETRUST_POLICY_MAC_APP_STORE = 1 << 6,
CORETRUST_POLICY_IPHONE_DEVELOPER = 1 << 7,
CORETRUST_POLICY_IPHONE_APP_PROD = 1 << 8,
CORETRUST_POLICY_IPHONE_APP_DEV = 1 << 9,
CORETRUST_POLICY_IPHONE_VPN_PROD = 1 << 10,
CORETRUST_POLICY_IPHONE_VPN_DEV = 1 << 11,
CORETRUST_POLICY_TVOS_APP_PROD = 1 << 12,
CORETRUST_POLICY_TVOS_APP_DEV = 1 << 13,
CORETRUST_POLICY_TEST_FLIGHT_PROD = 1 << 14,
CORETRUST_POLICY_TEST_FLIGHT_DEV = 1 << 15,
CORETRUST_POLICY_IPHONE_DISTRIBUTION = 1 << 16,
CORETRUST_POLICY_MAC_SUBMISSION = 1 << 17,
CORETRUST_POLICY_YONKERS_DEV = 1 << 18,
CORETRUST_POLICY_YONKERS_PROD = 1 << 19,
CORETRUST_POLICY_MAC_PLATFORM_G2 = 1 << 20,
CORETRUST_POLICY_ACRT = 1 << 21,
CORETRUST_POLICY_SATORI = 1 << 22,
CORETRUST_POLICY_BAA = 1 << 23,
CORETRUST_POLICY_BAA_SYSTEM = 1 << 23, // BAA and BAA_SYSTEM are the same
CORETRUST_POLICY_UCRT = 1 << 24,
CORETRUST_POLICY_PRAGUE = 1 << 25,
CORETRUST_POLICY_KDL = 1 << 26,
CORETRUST_POLICY_MFI_AUTHV2 = 1 << 27,
CORETRUST_POLICY_MFI_SW_AUTH_PROD = 1 << 28,
CORETRUST_POLICY_MFI_SW_AUTH_DEV = 1 << 29,
CORETRUST_POLICY_COMPONENT = 1 << 30,
CORETRUST_POLICY_IMG4 = 1ULL << 31,
CORETRUST_POLICY_SERVER_AUTH = 1ULL << 32,
CORETRUST_POLICY_SERVER_AUTH_STRING = 1ULL << 33,
CORETRUST_POLICY_MFI_AUTHV4_ACCESSORY = 1ULL << 34,
CORETRUST_POLICY_MFI_AUTHV4_ATTESTATION = 1ULL << 35,
CORETRUST_POLICY_MFI_AUTHV4_PROVISIONING = 1ULL << 36,
CORETRUST_POLICY_WWDR_CLOUD_MANAGED = 1ULL << 37,
CORETRUST_POLICY_HAVEN = 1ULL << 38,
CORETRUST_POLICY_PROVISIONING_PROFILE = 1ULL << 39,
CORETRUST_POLICY_SENSOR_PROD = 1ULL << 40,
CORETRUST_POLICY_SENSOR_DEV = 1ULL << 41,
CORETRUST_POLICY_BAA_USER = 1ULL << 42,
};
typedef CT_uint32_t CoreTrustDigestType;
enum {
CORETRUST_DIGEST_TYPE_SHA1 = 1,
CORETRUST_DIGEST_TYPE_SHA224 = 2,
CORETRUST_DIGEST_TYPE_SHA256 = 4,
CORETRUST_DIGEST_TYPE_SHA384 = 8,
CORETRUST_DIGEST_TYPE_SHA512 = 16
};
/*! @function CTParseAmfiCMS
@abstract Parse CMS signed data
@param cmsData pointer to beginning of the binary (BER-encoded) CMS object
@param cmsLen the length of the CMS object
@param maxDigestType maximum digest type supported by the client
@param leafCert return value, pointer to the verified leaf certificate
@param leafCertLen return value, length of the verified leaf certificate
@param contentData return value, pointer to the CMS content, if present
@param contentLen return value, length of the CMS content, if present
@param cmsDigestType return value, the digest type used to sign the CMS object
@param policyFlags return value, the CoreTrust policies that the chain may meet (based on leaf certificate only)
@return 0 upon success, a parsing error (see CTErrors.h)
*/
CT_int CTParseAmfiCMS(
const CT_uint8_t *__counted_by(cmsLen) cmsData, CT_size_t cmsLen,
CoreTrustDigestType maxDigestType,
const CT_uint8_t *__counted_by(*leafCertLen) *leafCert, CT_size_t *leafCertLen,
const CT_uint8_t *__counted_by(*contentLen) *contentData, CT_size_t *contentLen,
CoreTrustDigestType *cmsDigestType,
CoreTrustPolicyFlags *policyFlags);
/*! @function CTVerifyAmfiCMS
@abstract Verify CMS signed data signature
@param cmsData pointer to beginning of the binary (BER-encoded) CMS object
@param cmsLen the length of the CMS object
@param digestData pointer to beginning of the content data hash
@param digestLen the length of the content data hash
@param maxDigestType maximum digest type supported by the client
@param hashAgilityDigestType return value, the highest strength digest type available in the hash agility attribute
@param hashAgilityDigestData return value, pointer to the hash agility value
@param hashAgilityDigestLen return value, length of the hash agility value
@return 0 upon success, a parsing or validation error (see CTErrors.h)
@discussion
Returns non-zero if there's a standards-based problem with the CMS or certificates.
Some notes about hash agility outputs:
- hashAgilityDigestType is only non-zero for HashAgilityV2
- If hashAgilityDigestType is non-zero, digestData/Len provides the digest value
- If hashAgilityDigestType is zero, digestData/Len provides the content of the HashAgilityV1 attribute (if present)
- If neither HashAgilityV1 nor HashAgilityV2 attributes are found, these outputs will all be NULL.
*/
CT_int CTVerifyAmfiCMS(
const CT_uint8_t *__counted_by(cmsLen) cmsData, CT_size_t cmsLen,
const CT_uint8_t *__counted_by(digestLen) digestData, CT_size_t digestLen,
CoreTrustDigestType maxDigestType,
CoreTrustDigestType *hashAgilityDigestType,
const CT_uint8_t *__counted_by(*hashAgilityDigestLen) *hashAgilityDigestData, CT_size_t *hashAgilityDigestLen);
/*! @function CTVerifyAmfiCertificateChain
@abstract Verify CMS signed data certificate chain
@param cmsData pointer to beginning of the binary (BER-encoded) CMS object
@param cmsLen the length of the CMS object
@param allow_test_hierarchy allow the Test Apple roots to be used as anchors in addition to the production roots
@param maxDigestType maximum digest type supported by the client
@param policyFlags return value, the CoreTrust policies that the certificate chain met
@return 0 upon success, a parsing or validation error (see CTErrors.h)
@discussion
Returns non-zero if there's a standards-based problem with the CMS or certificates.
Policy matching of the certificates is only reflected in the policyFlags output. Namely, if the only problem is that
the certificates don't match a policy, the returned integer will be 0 (success) and the policyFlags will be 0 (no matching policies).
*/
CT_int CTVerifyAmfiCertificateChain(
const CT_uint8_t *__counted_by(cmsLen) cmsData, CT_size_t cmsLen,
CT_bool allow_test_hierarchy,
CoreTrustDigestType maxDigestType,
CoreTrustPolicyFlags *policyFlags);
/*! @function CTEvaluateAMFICodeSignatureCMS
@abstract Verify CMS signature and certificates against the AMFI policies
@param cmsData pointer to beginning of the binary (BER-encoded) CMS object
@param cmsLen the length of the CMS object
@param detachedData pointer to data that is signed by the CMS object
@param detachedDataLen the length of the signed data
@param allow_test_hierarchy allow the Test Apple roots to be used as anchors in addition to the production roots
@param leafCert return value, pointer to the verified leaf certificate
@param leafCertLen return value, length of the verified leaf certificate
@param policyFlags return value, the CoreTrust policies that the certificate chain met
@param cmsDigestType return value, the digest type used to sign the CMS object
@param hashAgilityDigestType return value, the highest strength digest type available in the hash agility attribute
@param digestData return value, pointer to the hash agility value
@param digestLen return value, length of the hash agility value
@return 0 upon success, a parsing or validation error (see CTErrors.h)
@discussion
Returns non-zero if there's a standards-based problem with the CMS or certificates.
Policy matching of the certificates is only reflected in the policyFlags output. Namely, if the only problem is that
the certificates don't match a policy, the returned integer will be 0 (success) and the policyFlags will be 0 (no matching policies).
Some notes about hash agility outputs:
- hashAgilityDigestType is only non-zero for HashAgilityV2
- If hashAgilityDigestType is non-zero, digestData/Len provides the digest value
- If hashAgilityDigestType is zero, digestData/Len provides the content of the HashAgilityV1 attribute (if present)
- If neither HashAgilityV1 nor HashAgilityV2 attributes are found, these outputs will all be NULL.
*/
CT_int CTEvaluateAMFICodeSignatureCMS(
const CT_uint8_t *__counted_by(cmsLen) cmsData, CT_size_t cmsLen,
const CT_uint8_t *__counted_by(detachedDataLen) detachedData, CT_size_t detachedDataLen,
CT_bool allow_test_hierarchy,
const CT_uint8_t *__counted_by(*leafCertLen) *leafCert, CT_size_t *leafCertLen,
CoreTrustPolicyFlags *policyFlags,
CoreTrustDigestType *cmsDigestType,
CoreTrustDigestType *hashAgilityDigestType,
const CT_uint8_t *__counted_by(*digestLen) *digestData, CT_size_t *digestLen);
/*! @function CTEvaluateAMFICodeSignatureCMS_MaxDigestType
@abstract Verify CMS signature and certificates against the AMFI policies
@param cmsData pointer to beginning of the binary (BER-encoded) CMS object
@param cmsLen the length of the CMS object
@param detachedData pointer to data that is signed by the CMS object
@param detachedDataLen the length of the signed data
@param allow_test_hierarchy allow the Test Apple roots to be used as anchors in addition to the production roots
@param maxDigestType maximum digest type supported by the client
@param leafCert return value, pointer to the verified leaf certificate
@param leafCertLen return value, length of the verified leaf certificate
@param policyFlags return value, the CoreTrust policies that the certificate chain met
@param cmsDigestType return value, the digest type used to sign the CMS object
@param hashAgilityDigestType return value, the highest strength digest type available and supported by client in the hash agility attribute
@param digestData return value, pointer to the hash agility value
@param digestLen return value, length of the hash agility value
@return 0 upon success, a parsing or validation error (see CTErrors.h)
@discussion
Returns non-zero if there's a standards-based problem with the CMS or certificates.
Policy matching of the certificates is only reflected in the policyFlags output. Namely, if the only problem is that
the certificates don't match a policy, the returned integer will be 0 (success) and the policyFlags will be 0 (no matching policies).
Some notes about hash agility outputs:
- hashAgilityDigestType is only non-zero for HashAgilityV2
- If hashAgilityDigestType is non-zero, digestData/Len provides the digest value
- If hashAgilityDigestType is zero, digestData/Len provides the content of the HashAgilityV1 attribute (if present)
- If neither HashAgilityV1 nor HashAgilityV2 attributes are found, these outputs will all be NULL.
*/
CT_int CTEvaluateAMFICodeSignatureCMS_MaxDigestType(
const CT_uint8_t *__counted_by(cmsLen) cmsData, CT_size_t cmsLen,
const CT_uint8_t *__counted_by(detachedDataLen) detachedData, CT_size_t detachedDataLen,
CT_bool allow_test_hierarchy,
CoreTrustDigestType maxDigestType,
const CT_uint8_t *__counted_by(*leafCertLen) *leafCert, CT_size_t *leafCertLen,
CoreTrustPolicyFlags *policyFlags,
CoreTrustDigestType *cmsDigestType,
CoreTrustDigestType *hashAgilityDigestType,
const CT_uint8_t *__counted_by(*digestLen) *digestData, CT_size_t *digestLen);
/*! @function CTEvaluateAMFICodeSignatureCMSPubKey
@abstract Verify CMS signature and certificates against the AMFI policies
@param cmsData pointer to beginning of the binary (BER-encoded) CMS object
@param cmsLen the length of the CMS object
@param detachedData pointer to data that is signed by the CMS object
@param detachedDataLen the length of the signed data
@param anchorPublicKey anchor public key for self-signed certificate
@param anchorPublicKeyLen length of the anchor public key
@param cmsDigestType return value, the digest type used to sign the CMS object
@param hashAgilityDigestType return value, the highest strength digest type available and supported by client in the hash agility attribute
@param digestData return value, pointer to the hash agility value
@param digestLen return value, length of the hash agility value
@return 0 upon success, a parsing or validation error (see CTErrors.h)
@discussion
Returns non-zero if there's a standards-based problem with the CMS or certificates.
Policy matching of the certificates is only reflected in the policyFlags output. Namely, if the only problem is that
the certificates don't match a policy, the returned integer will be 0 (success) and the policyFlags will be 0 (no matching policies).
Some notes about hash agility outputs:
- hashAgilityDigestType is only non-zero for HashAgilityV2
- If hashAgilityDigestType is non-zero, digestData/Len provides the digest value
- If hashAgilityDigestType is zero, digestData/Len provides the content of the HashAgilityV1 attribute (if present)
- If neither HashAgilityV1 nor HashAgilityV2 attributes are found, these outputs will all be NULL.
*/
int CTEvaluateAMFICodeSignatureCMSPubKey(
const CT_uint8_t *__counted_by(cmsLen) cmsData, CT_size_t cmsLen,
const CT_uint8_t *__counted_by(detachedDataLen) detachedData, CT_size_t detachedDataLen,
const CT_uint8_t *__counted_by(anchorPublicKeyLen) anchorPublicKey, CT_size_t anchorPublicKeyLen,
CoreTrustDigestType *cmsDigestType,
CoreTrustDigestType *hashAgilityDigestType,
const CT_uint8_t *__counted_by(*digestLen) *digestData, CT_size_t *digestLen);
/*! @function CTParseAccessoryCerts
@abstract Parse a CMS or binary encoded set of certificates and return the leaf and subCA(s)
@param certsData pointer to beginning of the binary (DER-encoded) certificates or binary (BER-encoded) CMS object
@param certsLen the length of the input certificates
@param leafCertData return value, pointer to the leaf certificate
@param leafCertLen return value, length of the leaf certificate
@param subCACertData return value, pointer to the subCA certificate(s), if present, null otherwise
@param subCACertLen return value, length of the subCA certificates
@param flags return value, the policy flags set by the leaf certificate (to indicate which type of accessory cert)
@return 0 upon success, a parsing error (see CTErrors.h) */
CT_int CTParseAccessoryCerts(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(*leafCertLen) *leafCertData, CT_size_t *leafCertLen,
const CT_uint8_t *__counted_by(*subCACertLen) *subCACertData, CT_size_t *subCACertLen,
CoreTrustPolicyFlags *flags);
/*! @function CTEvaluateAccessoryCert
@abstract Verify certificates against a specified accessory policy and anchor
@param leafCertData pointer to beginning of the binary (DER-encoded) leaf certificate
@param leafCertLen the length of the leaf certificate
@param subCACertData optional pointer to beginning of the binary (DER-encoded) subCA certificate(s)
@param subCACertLen the length of thesubCA certificate(s)
@param anchorCertData pointer to beginning of the binary (DER-encoded) anchor certificate
@param anchorCertLen the length of the anchor certificate
@param policy the policy to verify the certificates against, see discussion
@param leafKeyData return value, pointer to the key in the verified leaf certificate
@param leafKeyLen return value, length of the key in the verified leaf certificate
@param extensionValueData return value, pointer to the extension value in the verified leaf certificate, see discussion
@param extensionValueLen return value, length of the extension value in the verified leaf certificate
@return 0 upon success, a parsing or validation error (see CTErrors.h)
@discussion It is expected that callers will first use CTParseAccessoryCerts and then pass that data into CTEvaluateAccessoryCert.
Which extension value is returned is based on which policy the cert was verified against:
- For MFI AuthV3, this is the value of the extension with OID 1.2.840.113635.100.6.36
- For SW Auth, this is the value of the extension with OID 1.2.840.113635.100.6.59.1 (GeneralCapabilities extension)
- For Component certs, this si the value of the extension with OID 1.2.840.113635.100.11.1 (Component Type)
- For MFi AuthV4, this is the value of the extension with OID 1.2.840.113635.100.6.71.1 (Apple Accessory Properties extension)
The following CoreTrustPolicyFlags are accepted:
- CORETRUST_POLICY_BASIC
- CORETRUST_POLICY_MFI_AUTHV2
- CORETRUST_POLICY_MFI_AUTHV3
- CORETRUST_POLICY_MFI_SW_AUTH_DEV
- CORETRUST_POLICY_MFI_SW_AUTH_PROD
- CORETRUST_POLICY_COMPONENT
- CORETRUST_POLICY_MFI_AUTHV4_ACCESSORY
- CORETRUST_POLICY_MFI_AUTHV4_ATTESTATION
- CORETRUST_POLICY_MFI_AUTHV4_PROVISIONING
*/
CT_int CTEvaluateAccessoryCert(
const CT_uint8_t *__counted_by(leafCertLen) leafCertData, CT_size_t leafCertLen,
const CT_uint8_t *__counted_by(subCACertLen) subCACertData, CT_size_t subCACertLen,
const CT_uint8_t *__counted_by(anchorCertLen) anchorCertData, CT_size_t anchorCertLen,
CoreTrustPolicyFlags policy,
const CT_uint8_t *__counted_by(*leafKeyLen) *leafKeyData, CT_size_t *leafKeyLen,
const CT_uint8_t *__counted_by(*extensionValueLen) *extensionValueData, CT_size_t *extensionValueLen);
/*! @function CTEvaluateAppleSSL
@abstract Verify certificates against an Apple SSL pinning policy
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param hostnameData the hostname of the server being connected to
@param hostnameLen length of the hostname
@param leafMarker the last decimat of the leaf marker OID for this project (e.g. 32 for 1.2.840.113635.100.6.27.32)
@param allowTestRoots allow the Test Apple roots to be used as anchors in addition to the production roots
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateAppleSSL(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(hostnameLen) hostnameData, CT_size_t hostnameLen,
CT_uint64_t leafMarker,
CT_bool allowTestRoots);
/*! @function CTEvaluateAppleSSLWithOptionalTemporalCheck
@abstract Verify certificates against an Apple SSL pinning policy
@param certsData pointer to beginning of the binary (DER-encoded) certificates (leaf first)
@param certsLen the length of the certificates byte array
@param hostnameData the hostname of the server being connected to
@param hostnameLen length of the hostname
@param leafMarker the last decimat of the leaf marker OID for this project (e.g. 32 for 1.2.840.113635.100.6.27.32)
@param allowTestRoots allow the Test Apple roots to be used as anchors in addition to the production roots
@param checkTemporalValidity indicate whether to check the temporal validity of certificates
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
CT_int CTEvaluateAppleSSLWithOptionalTemporalCheck(
const CT_uint8_t *__counted_by(certsLen) certsData, CT_size_t certsLen,
const CT_uint8_t *__counted_by(hostnameLen) hostnameData, CT_size_t hostnameLen,
CT_uint64_t leafMarker,
CT_bool allowTestRoots,
CT_bool checkTemporalValidity);
/*! @function CTEvaluateProvisioningProfile
@abstract Parse and verify the certificates of a signed provisioning profile
@param provisioningProfileData pointer to beginning of the binary (BER-encoded) provisioning profile CMS object
@param provisioningProfileLen the length of the provisioning profile
@param allowTestRoots allow the Test Apple roots to be used as anchors in addition to the production roots
@param contentData return value, pointer to the profile content
@param contentLen return value, length of the profile content
@return 0 upon success, a parsing or validation error (see CTErrors.h) */
int CTEvaluateProvisioningProfile(
const CT_uint8_t *__counted_by(provisioningProfileLen) provisioningProfileData, CT_size_t provisioningProfileLen,
CT_bool allowTestRoots,
const CT_uint8_t *__counted_by(*contentLen) *contentData, CT_size_t *contentLen);
__END_DECLS
#endif /* _CORETRUST_EVALUATE_H_ */

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
<plist version="0.9">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIdentifier</key>
<string>com.apple.framework.kernel</string>
<key>CFBundleName</key>
<string>Kernel</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>###KERNEL_VERSION_SHORT###</string>
<key>CFBundleVersion</key>
<string>###KERNEL_VERSION_LONG###</string>
<key>CFBundleSignature</key>
<string>????</string>
</dict>
</plist>

View file

@ -0,0 +1,58 @@
export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd
export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def
export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule
export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir
include $(MakeInc_cmd)
include $(MakeInc_def)
INSTINC_SUBDIRS = \
architecture \
mach-o \
sys
INSTINC_SUBDIRS_X86_64 = \
architecture
INSTINC_SUBDIRS_X86_64H = \
architecture
INSTINC_SUBDIRS_ARM = \
architecture
INSTINC_SUBDIRS_ARM64 = \
architecture
EXPORT_FILES = \
Availability.h \
AvailabilityInternal.h \
AvailabilityMacros.h
KERNEL_FILES = \
stdarg.h \
stdatomic.h \
stdbool.h \
stddef.h \
stdint.h \
ptrauth.h
LIBCXX_DATAFILES = \
stddef.h \
stdint.h
INSTALL_KF_LIBCXX_MI_LIST = ${LIBCXX_DATAFILES}
INSTALL_MI_LIST =
INSTALL_MI_DIR = .
INSTALL_KF_MI_LIST = ${KERNEL_FILES}
INSTALL_KF_MI_LCL_LIST = ${KERNEL_FILES}
EXPORT_MI_LIST = ${EXPORT_FILES} ${KERNEL_FILES}
EXPORT_MI_DIR = .
include $(MakeInc_rule)
include $(MakeInc_dir)

View file

@ -0,0 +1,462 @@
/******************************************************************************
*
* Name: actbl.h - Basic ACPI Table Definitions
* $Revision: 1.7 $
*
*****************************************************************************/
/******************************************************************************
*
* 1. Copyright Notice
*
* Some or all of this work - Copyright (c) 1999 - 2006, Intel Corp.
* All rights reserved.
*
* 2. License
*
* 2.1. This is your license from Intel Corp. under its intellectual property
* rights. You may have additional license terms from the party that provided
* you this software, covering your right to use that party's intellectual
* property rights.
*
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
* copy of the source code appearing in this file ("Covered Code") an
* irrevocable, perpetual, worldwide license under Intel's copyrights in the
* base code distributed originally by Intel ("Original Intel Code") to copy,
* make derivatives, distribute, use and display any portion of the Covered
* Code in any form, with the right to sublicense such rights; and
*
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
* license (with the right to sublicense), under only those claims of Intel
* patents that are infringed by the Original Intel Code, to make, use, sell,
* offer to sell, and import the Covered Code and derivative works thereof
* solely to the minimum extent necessary to exercise the above copyright
* license, and in no event shall the patent license extend to any additions
* to or modifications of the Original Intel Code. No other license or right
* is granted directly or by implication, estoppel or otherwise;
*
* The above copyright and patent license is granted only if the following
* conditions are met:
*
* 3. Conditions
*
* 3.1. Redistribution of Source with Rights to Further Distribute Source.
* Redistribution of source code of any substantial portion of the Covered
* Code or modification with rights to further distribute source must include
* the above Copyright Notice, the above License, this list of Conditions,
* and the following Disclaimer and Export Compliance provision. In addition,
* Licensee must cause all Covered Code to which Licensee contributes to
* contain a file documenting the changes Licensee made to create that Covered
* Code and the date of any change. Licensee must include in that file the
* documentation of any changes made by any predecessor Licensee. Licensee
* must include a prominent statement that the modification is derived,
* directly or indirectly, from Original Intel Code.
*
* 3.2. Redistribution of Source with no Rights to Further Distribute Source.
* Redistribution of source code of any substantial portion of the Covered
* Code or modification without rights to further distribute source must
* include the following Disclaimer and Export Compliance provision in the
* documentation and/or other materials provided with distribution. In
* addition, Licensee may not authorize further sublicense of source of any
* portion of the Covered Code, and must include terms to the effect that the
* license from Licensee to its licensee is limited to the intellectual
* property embodied in the software Licensee provides to its licensee, and
* not to intellectual property embodied in modifications its licensee may
* make.
*
* 3.3. Redistribution of Executable. Redistribution in executable form of any
* substantial portion of the Covered Code or modification must reproduce the
* above Copyright Notice, and the following Disclaimer and Export Compliance
* provision in the documentation and/or other materials provided with the
* distribution.
*
* 3.4. Intel retains all right, title, and interest in and to the Original
* Intel Code.
*
* 3.5. Neither the name Intel nor any other trademark owned or controlled by
* Intel shall be used in advertising or otherwise to promote the sale, use or
* other dealings in products derived from or relating to the Covered Code
* without prior written authorization from Intel.
*
* 4. Disclaimer and Export Compliance
*
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
* LIMITED REMEDY.
*
* 4.3. Licensee shall not export, either directly or indirectly, any of this
* software or system incorporating such software without first obtaining any
* required license or other approval from the U. S. Department of Commerce or
* any other agency or department of the United States Government. In the
* event Licensee exports any such software from the United States or
* re-exports any such software from a foreign destination, Licensee shall
* ensure that the distribution and export/re-export of the software is in
* compliance with all laws, regulations, orders, or other restrictions of the
* U.S. Export Administration Regulations. Licensee agrees that neither it nor
* any of its subsidiaries will export/re-export any technical data, process,
* software, or service, directly or indirectly, to any country for which the
* United States government or any agency thereof requires an export license,
* other governmental approval, or letter of assurance, without first obtaining
* such license, approval or letter.
*
*****************************************************************************/
#ifndef __ACTBL_H__
#define __ACTBL_H__
/*
* Values for description table header signatures. Useful because they make
* it more difficult to inadvertently type in the wrong signature.
*/
#define DSDT_SIG "DSDT" /* Differentiated System Description Table */
#define FADT_SIG "FACP" /* Fixed ACPI Description Table */
#define FACS_SIG "FACS" /* Firmware ACPI Control Structure */
#define PSDT_SIG "PSDT" /* Persistent System Description Table */
#define RSDP_SIG "RSD PTR " /* Root System Description Pointer */
#define RSDT_SIG "RSDT" /* Root System Description Table */
#define XSDT_SIG "XSDT" /* Extended System Description Table */
#define SSDT_SIG "SSDT" /* Secondary System Description Table */
#define RSDP_NAME "RSDP"
/*
* All tables and structures must be byte-packed to match the ACPI
* specification, since the tables are provided by the system BIOS
*/
#pragma pack(1)
/*
* These are the ACPI tables that are directly consumed by the subsystem.
*
* The RSDP and FACS do not use the common ACPI table header. All other ACPI
* tables use the header.
*
* Note about bitfields: The UINT8 type is used for bitfields in ACPI tables.
* This is the only type that is even remotely portable. Anything else is not
* portable, so do not use any other bitfield types.
*/
/*******************************************************************************
*
* ACPI Table Header. This common header is used by all tables except the
* RSDP and FACS. The define is used for direct inclusion of header into
* other ACPI tables
*
******************************************************************************/
#define ACPI_TABLE_HEADER_DEF \
char Signature[4]; /* ASCII table signature */ \
UINT32 Length; /* Length of table in bytes, including this header */ \
UINT8 Revision; /* ACPI Specification minor version # */ \
UINT8 Checksum; /* To make sum of entire table == 0 */ \
char OemId[6]; /* ASCII OEM identification */ \
char OemTableId[8]; /* ASCII OEM table identification */ \
UINT32 OemRevision; /* OEM revision number */ \
char AslCompilerId[4]; /* ASCII ASL compiler vendor ID */ \
UINT32 AslCompilerRevision; /* ASL compiler version */
typedef struct acpi_table_header {
ACPI_TABLE_HEADER_DEF
} ACPI_TABLE_HEADER;
/*
* GAS - Generic Address Structure (ACPI 2.0+)
*/
typedef struct acpi_generic_address {
UINT8 AddressSpaceId; /* Address space where struct or register exists */
UINT8 RegisterBitWidth; /* Size in bits of given register */
UINT8 RegisterBitOffset; /* Bit offset within the register */
UINT8 AccessWidth; /* Minimum Access size (ACPI 3.0) */
UINT64 Address; /* 64-bit address of struct or register */
} ACPI_GENERIC_ADDRESS;
/*******************************************************************************
*
* RSDP - Root System Description Pointer (Signature is "RSD PTR ")
*
******************************************************************************/
typedef struct rsdp_descriptor {
char Signature[8]; /* ACPI signature, contains "RSD PTR " */
UINT8 Checksum; /* ACPI 1.0 checksum */
char OemId[6]; /* OEM identification */
UINT8 Revision; /* Must be (0) for ACPI 1.0 or (2) for ACPI 2.0+ */
UINT32 RsdtPhysicalAddress;/* 32-bit physical address of the RSDT */
UINT32 Length; /* Table length in bytes, including header (ACPI 2.0+) */
UINT64 XsdtPhysicalAddress;/* 64-bit physical address of the XSDT (ACPI 2.0+) */
UINT8 ExtendedChecksum; /* Checksum of entire table (ACPI 2.0+) */
UINT8 Reserved[3]; /* Reserved, must be zero */
} RSDP_DESCRIPTOR;
#define ACPI_RSDP_REV0_SIZE 20 /* Size of original ACPI 1.0 RSDP */
/*******************************************************************************
*
* RSDT/XSDT - Root System Description Tables
*
******************************************************************************/
typedef struct rsdt_descriptor {
ACPI_TABLE_HEADER_DEF
UINT32 TableOffsetEntry[1];/* Array of pointers to ACPI tables */
} RSDT_DESCRIPTOR;
typedef struct xsdt_descriptor {
ACPI_TABLE_HEADER_DEF
UINT64 TableOffsetEntry[1];/* Array of pointers to ACPI tables */
} XSDT_DESCRIPTOR;
/*******************************************************************************
*
* FACS - Firmware ACPI Control Structure (FACS)
*
******************************************************************************/
typedef struct facs_descriptor {
char Signature[4]; /* ASCII table signature */
UINT32 Length; /* Length of structure, in bytes */
UINT32 HardwareSignature; /* Hardware configuration signature */
UINT32 FirmwareWakingVector;/* 32-bit physical address of the Firmware Waking Vector */
UINT32 GlobalLock; /* Global Lock for shared hardware resources */
/* Flags (32 bits) */
UINT8 S4Bios_f : 1;/* 00: S4BIOS support is present */
UINT8 : 7;/* 01-07: Reserved, must be zero */
UINT8 Reserved1[3]; /* 08-31: Reserved, must be zero */
UINT64 XFirmwareWakingVector;/* 64-bit version of the Firmware Waking Vector (ACPI 2.0+) */
UINT8 Version; /* Version of this table (ACPI 2.0+) */
UINT8 Reserved[31]; /* Reserved, must be zero */
} FACS_DESCRIPTOR;
#define ACPI_GLOCK_PENDING 0x01 /* 00: Pending global lock ownership */
#define ACPI_GLOCK_OWNED 0x02 /* 01: Global lock is owned */
/*
* Common FACS - This is a version-independent FACS structure used for internal use only
*/
typedef struct acpi_common_facs {
UINT32 *GlobalLock;
UINT64 *FirmwareWakingVector;
UINT8 VectorWidth;
} ACPI_COMMON_FACS;
/*******************************************************************************
*
* FADT - Fixed ACPI Description Table (Signature "FACP")
*
******************************************************************************/
/* Fields common to all versions of the FADT */
#define ACPI_FADT_COMMON \
ACPI_TABLE_HEADER_DEF \
UINT32 V1_FirmwareCtrl; /* 32-bit physical address of FACS */ \
UINT32 V1_Dsdt; /* 32-bit physical address of DSDT */ \
UINT8 Reserved1; /* System Interrupt Model isn't used in ACPI 2.0*/ \
UINT8 Prefer_PM_Profile; /* Conveys preferred power management profile to OSPM. */ \
UINT16 SciInt; /* System vector of SCI interrupt */ \
UINT32 SmiCmd; /* Port address of SMI command port */ \
UINT8 AcpiEnable; /* Value to write to smi_cmd to enable ACPI */ \
UINT8 AcpiDisable; /* Value to write to smi_cmd to disable ACPI */ \
UINT8 S4BiosReq; /* Value to write to SMI CMD to enter S4BIOS state */ \
UINT8 PstateCnt; /* Processor performance state control*/ \
UINT32 V1_Pm1aEvtBlk; /* Port address of Power Mgt 1a Event Reg Blk */ \
UINT32 V1_Pm1bEvtBlk; /* Port address of Power Mgt 1b Event Reg Blk */ \
UINT32 V1_Pm1aCntBlk; /* Port address of Power Mgt 1a Control Reg Blk */ \
UINT32 V1_Pm1bCntBlk; /* Port address of Power Mgt 1b Control Reg Blk */ \
UINT32 V1_Pm2CntBlk; /* Port address of Power Mgt 2 Control Reg Blk */ \
UINT32 V1_PmTmrBlk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ \
UINT32 V1_Gpe0Blk; /* Port addr of General Purpose AcpiEvent 0 Reg Blk */ \
UINT32 V1_Gpe1Blk; /* Port addr of General Purpose AcpiEvent 1 Reg Blk */ \
UINT8 Pm1EvtLen; /* Byte Length of ports at pm1X_evt_blk */ \
UINT8 Pm1CntLen; /* Byte Length of ports at pm1X_cnt_blk */ \
UINT8 Pm2CntLen; /* Byte Length of ports at pm2_cnt_blk */ \
UINT8 PmTmLen; /* Byte Length of ports at pm_tm_blk */ \
UINT8 Gpe0BlkLen; /* Byte Length of ports at gpe0_blk */ \
UINT8 Gpe1BlkLen; /* Byte Length of ports at gpe1_blk */ \
UINT8 Gpe1Base; /* Offset in gpe model where gpe1 events start */ \
UINT8 CstCnt; /* Support for the _CST object and C States change notification.*/ \
UINT16 Plvl2Lat; /* Worst case HW latency to enter/exit C2 state */ \
UINT16 Plvl3Lat; /* Worst case HW latency to enter/exit C3 state */ \
UINT16 FlushSize; /* Processor's memory cache line width, in bytes */ \
UINT16 FlushStride; /* Number of flush strides that need to be read */ \
UINT8 DutyOffset; /* Processor's duty cycle index in processor's P_CNT reg*/ \
UINT8 DutyWidth; /* Processor's duty cycle value bit width in P_CNT register.*/ \
UINT8 DayAlrm; /* Index to day-of-month alarm in RTC CMOS RAM */ \
UINT8 MonAlrm; /* Index to month-of-year alarm in RTC CMOS RAM */ \
UINT8 Century; /* Index to century in RTC CMOS RAM */ \
UINT16 IapcBootArch; /* IA-PC Boot Architecture Flags. See Table 5-10 for description*/ \
UINT8 Reserved2; /* Reserved, must be zero */
/*
* ACPI 2.0+ FADT
*/
typedef struct fadt_descriptor {
ACPI_FADT_COMMON
/* Flags (32 bits) */
UINT8 WbInvd : 1;/* 00: The wbinvd instruction works properly */
UINT8 WbInvdFlush : 1;/* 01: The wbinvd flushes but does not invalidate */
UINT8 ProcC1 : 1;/* 02: All processors support C1 state */
UINT8 Plvl2Up : 1;/* 03: C2 state works on MP system */
UINT8 PwrButton : 1;/* 04: Power button is handled as a generic feature */
UINT8 SleepButton : 1;/* 05: Sleep button is handled as a generic feature, or not present */
UINT8 FixedRTC : 1;/* 06: RTC wakeup stat not in fixed register space */
UINT8 Rtcs4 : 1;/* 07: RTC wakeup stat not possible from S4 */
UINT8 TmrValExt : 1;/* 08: tmr_val is 32 bits 0=24-bits */
UINT8 DockCap : 1;/* 09: Docking supported */
UINT8 ResetRegSup : 1;/* 10: System reset via the FADT RESET_REG supported */
UINT8 SealedCase : 1;/* 11: No internal expansion capabilities and case is sealed */
UINT8 Headless : 1;/* 12: No local video capabilities or local input devices */
UINT8 CpuSwSleep : 1;/* 13: Must execute native instruction after writing SLP_TYPx register */
UINT8 PciExpWak : 1;/* 14: System supports PCIEXP_WAKE (STS/EN) bits (ACPI 3.0) */
UINT8 UsePlatformClock : 1;/* 15: OSPM should use platform-provided timer (ACPI 3.0) */
UINT8 S4RtcStsValid : 1;/* 16: Contents of RTC_STS valid after S4 wake (ACPI 3.0) */
UINT8 RemotePowerOnCapable : 1;/* 17: System is compatible with remote power on (ACPI 3.0) */
UINT8 ForceApicClusterModel : 1;/* 18: All local APICs must use cluster model (ACPI 3.0) */
UINT8 ForceApicPhysicalDestinationMode : 1;/* 19: All local xAPICs must use physical dest mode (ACPI 3.0) */
UINT8 : 4;/* 20-23: Reserved, must be zero */
UINT8 Reserved3; /* 24-31: Reserved, must be zero */
ACPI_GENERIC_ADDRESS ResetRegister; /* Reset register address in GAS format */
UINT8 ResetValue; /* Value to write to the ResetRegister port to reset the system */
UINT8 Reserved4[3]; /* These three bytes must be zero */
UINT64 XFirmwareCtrl; /* 64-bit physical address of FACS */
UINT64 XDsdt; /* 64-bit physical address of DSDT */
ACPI_GENERIC_ADDRESS XPm1aEvtBlk; /* Extended Power Mgt 1a AcpiEvent Reg Blk address */
ACPI_GENERIC_ADDRESS XPm1bEvtBlk; /* Extended Power Mgt 1b AcpiEvent Reg Blk address */
ACPI_GENERIC_ADDRESS XPm1aCntBlk; /* Extended Power Mgt 1a Control Reg Blk address */
ACPI_GENERIC_ADDRESS XPm1bCntBlk; /* Extended Power Mgt 1b Control Reg Blk address */
ACPI_GENERIC_ADDRESS XPm2CntBlk; /* Extended Power Mgt 2 Control Reg Blk address */
ACPI_GENERIC_ADDRESS XPmTmrBlk; /* Extended Power Mgt Timer Ctrl Reg Blk address */
ACPI_GENERIC_ADDRESS XGpe0Blk; /* Extended General Purpose AcpiEvent 0 Reg Blk address */
ACPI_GENERIC_ADDRESS XGpe1Blk; /* Extended General Purpose AcpiEvent 1 Reg Blk address */
} FADT_DESCRIPTOR;
/*
* "Down-revved" ACPI 2.0 FADT descriptor
* Defined here to allow compiler to generate the length of the struct
*/
typedef struct fadt_descriptor_rev2_minus {
ACPI_FADT_COMMON
UINT32 Flags;
ACPI_GENERIC_ADDRESS ResetRegister; /* Reset register address in GAS format */
UINT8 ResetValue; /* Value to write to the ResetRegister port to reset the system. */
UINT8 Reserved7[3]; /* Reserved, must be zero */
} FADT_DESCRIPTOR_REV2_MINUS;
/*
* ACPI 1.0 FADT
* Defined here to allow compiler to generate the length of the struct
*/
typedef struct fadt_descriptor_rev1 {
ACPI_FADT_COMMON
UINT32 Flags;
} FADT_DESCRIPTOR_REV1;
/* FADT: Prefered Power Management Profiles */
#define PM_UNSPECIFIED 0
#define PM_DESKTOP 1
#define PM_MOBILE 2
#define PM_WORKSTATION 3
#define PM_ENTERPRISE_SERVER 4
#define PM_SOHO_SERVER 5
#define PM_APPLIANCE_PC 6
/* FADT: Boot Arch Flags */
#define BAF_LEGACY_DEVICES 0x0001
#define BAF_8042_KEYBOARD_CONTROLLER 0x0002
#define FADT2_REVISION_ID 3
#define FADT2_MINUS_REVISION_ID 2
/* Reset to default packing */
#pragma pack()
/*
* This macro is temporary until the table bitfield flag definitions
* are removed and replaced by a Flags field.
*/
#define ACPI_FLAG_OFFSET(d, f, o) (UINT8) (ACPI_OFFSET (d,f) +\
sizeof(((d *)0)->f) + o)
/*
* Get the remaining ACPI tables
*/
#include "Acpi_v1.h"
/*
* ACPI Table information. We save the table address, length,
* and type of memory allocation (mapped or allocated) for each
* table for 1) when we exit, and 2) if a new table is installed
*/
#define ACPI_MEM_NOT_ALLOCATED 0
#define ACPI_MEM_ALLOCATED 1
#define ACPI_MEM_MAPPED 2
/* Definitions for the Flags bitfield member of ACPI_TABLE_SUPPORT */
#define ACPI_TABLE_SINGLE 0x00
#define ACPI_TABLE_MULTIPLE 0x01
#define ACPI_TABLE_EXECUTABLE 0x02
#define ACPI_TABLE_ROOT 0x00
#define ACPI_TABLE_PRIMARY 0x10
#define ACPI_TABLE_SECONDARY 0x20
#define ACPI_TABLE_ALL 0x30
#define ACPI_TABLE_TYPE_MASK 0x30
/* Data about each known table type */
typedef struct acpi_table_support {
char *Name;
char *Signature;
void **GlobalPtr;
UINT8 SigLength;
UINT8 Flags;
} ACPI_TABLE_SUPPORT;
/* Macros used to generate offsets to specific table fields */
#define ACPI_FACS_OFFSET(f) (UINT8) ACPI_OFFSET (FACS_DESCRIPTOR,f)
#define ACPI_FADT_OFFSET(f) (UINT8) ACPI_OFFSET (FADT_DESCRIPTOR, f)
#define ACPI_GAS_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_GENERIC_ADDRESS,f)
#define ACPI_HDR_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_TABLE_HEADER,f)
#define ACPI_RSDP_OFFSET(f) (UINT8) ACPI_OFFSET (RSDP_DESCRIPTOR,f)
#define ACPI_FADT_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (FADT_DESCRIPTOR,f,o)
#define ACPI_FACS_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (FACS_DESCRIPTOR,f,o)
#endif /* __ACTBL_H__ */

View file

@ -0,0 +1,781 @@
/******************************************************************************
*
* Name: actbl1.h - Additional ACPI table definitions
* $Revision: 1.6 $
*
*****************************************************************************/
/******************************************************************************
*
* 1. Copyright Notice
*
* Some or all of this work - Copyright (c) 1999 - 2006, Intel Corp.
* All rights reserved.
*
* 2. License
*
* 2.1. This is your license from Intel Corp. under its intellectual property
* rights. You may have additional license terms from the party that provided
* you this software, covering your right to use that party's intellectual
* property rights.
*
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
* copy of the source code appearing in this file ("Covered Code") an
* irrevocable, perpetual, worldwide license under Intel's copyrights in the
* base code distributed originally by Intel ("Original Intel Code") to copy,
* make derivatives, distribute, use and display any portion of the Covered
* Code in any form, with the right to sublicense such rights; and
*
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
* license (with the right to sublicense), under only those claims of Intel
* patents that are infringed by the Original Intel Code, to make, use, sell,
* offer to sell, and import the Covered Code and derivative works thereof
* solely to the minimum extent necessary to exercise the above copyright
* license, and in no event shall the patent license extend to any additions
* to or modifications of the Original Intel Code. No other license or right
* is granted directly or by implication, estoppel or otherwise;
*
* The above copyright and patent license is granted only if the following
* conditions are met:
*
* 3. Conditions
*
* 3.1. Redistribution of Source with Rights to Further Distribute Source.
* Redistribution of source code of any substantial portion of the Covered
* Code or modification with rights to further distribute source must include
* the above Copyright Notice, the above License, this list of Conditions,
* and the following Disclaimer and Export Compliance provision. In addition,
* Licensee must cause all Covered Code to which Licensee contributes to
* contain a file documenting the changes Licensee made to create that Covered
* Code and the date of any change. Licensee must include in that file the
* documentation of any changes made by any predecessor Licensee. Licensee
* must include a prominent statement that the modification is derived,
* directly or indirectly, from Original Intel Code.
*
* 3.2. Redistribution of Source with no Rights to Further Distribute Source.
* Redistribution of source code of any substantial portion of the Covered
* Code or modification without rights to further distribute source must
* include the following Disclaimer and Export Compliance provision in the
* documentation and/or other materials provided with distribution. In
* addition, Licensee may not authorize further sublicense of source of any
* portion of the Covered Code, and must include terms to the effect that the
* license from Licensee to its licensee is limited to the intellectual
* property embodied in the software Licensee provides to its licensee, and
* not to intellectual property embodied in modifications its licensee may
* make.
*
* 3.3. Redistribution of Executable. Redistribution in executable form of any
* substantial portion of the Covered Code or modification must reproduce the
* above Copyright Notice, and the following Disclaimer and Export Compliance
* provision in the documentation and/or other materials provided with the
* distribution.
*
* 3.4. Intel retains all right, title, and interest in and to the Original
* Intel Code.
*
* 3.5. Neither the name Intel nor any other trademark owned or controlled by
* Intel shall be used in advertising or otherwise to promote the sale, use or
* other dealings in products derived from or relating to the Covered Code
* without prior written authorization from Intel.
*
* 4. Disclaimer and Export Compliance
*
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
* PARTICULAR PURPOSE.
*
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
* LIMITED REMEDY.
*
* 4.3. Licensee shall not export, either directly or indirectly, any of this
* software or system incorporating such software without first obtaining any
* required license or other approval from the U. S. Department of Commerce or
* any other agency or department of the United States Government. In the
* event Licensee exports any such software from the United States or
* re-exports any such software from a foreign destination, Licensee shall
* ensure that the distribution and export/re-export of the software is in
* compliance with all laws, regulations, orders, or other restrictions of the
* U.S. Export Administration Regulations. Licensee agrees that neither it nor
* any of its subsidiaries will export/re-export any technical data, process,
* software, or service, directly or indirectly, to any country for which the
* United States government or any agency thereof requires an export license,
* other governmental approval, or letter of assurance, without first obtaining
* such license, approval or letter.
*
*****************************************************************************/
#ifndef __ACTBL1_H__
#define __ACTBL1_H__
/*******************************************************************************
*
* Additional ACPI Tables
*
* These tables are not consumed directly by the ACPICA subsystem, but are
* included here to support device drivers and the AML disassembler.
*
******************************************************************************/
/*
* Values for description table header signatures. Useful because they make
* it more difficult to inadvertently type in the wrong signature.
*/
#define ACPI_SIG_ASF "ASF!" /* Alert Standard Format table */
#define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */
#define ACPI_SIG_CPEP "CPEP" /* Corrected Platform Error Polling table */
#define ACPI_SIG_DBGP "DBGP" /* Debug Port table */
#define ACPI_SIG_ECDT "ECDT" /* Embedded Controller Boot Resources Table */
#define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */
#define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */
#define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */
#define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */
#define ACPI_SIG_SLIT "SLIT" /* System Locality Distance Information Table */
#define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */
#define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */
#define ACPI_SIG_SRAT "SRAT" /* System Resource Affinity Table */
#define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */
#define ACPI_SIG_WDRT "WDRT" /* Watchdog Resource Table */
/* Legacy names */
#define APIC_SIG "APIC" /* Multiple APIC Description Table */
#define BOOT_SIG "BOOT" /* Simple Boot Flag Table */
#define SBST_SIG "SBST" /* Smart Battery Specification Table */
/*
* All tables must be byte-packed to match the ACPI specification, since
* the tables are provided by the system BIOS.
*/
#pragma pack(1)
/*
* Note about bitfields: The UINT8 type is used for bitfields in ACPI tables.
* This is the only type that is even remotely portable. Anything else is not
* portable, so do not use any other bitfield types.
*/
/*******************************************************************************
*
* ASF - Alert Standard Format table (Signature "ASF!")
*
******************************************************************************/
typedef struct acpi_table_asf {
ACPI_TABLE_HEADER_DEF
} ACPI_TABLE_ASF;
#define ACPI_ASF_HEADER_DEF \
UINT8 Type; \
UINT8 Reserved; \
UINT16 Length;
typedef struct acpi_asf_header {
ACPI_ASF_HEADER_DEF
} ACPI_ASF_HEADER;
/* Values for Type field */
#define ASF_INFO 0
#define ASF_ALERT 1
#define ASF_CONTROL 2
#define ASF_BOOT 3
#define ASF_ADDRESS 4
#define ASF_RESERVED 5
/*
* ASF subtables
*/
/* 0: ASF Information */
typedef struct acpi_asf_info {
ACPI_ASF_HEADER_DEF
UINT8 MinResetValue;
UINT8 MinPollInterval;
UINT16 SystemId;
UINT32 MfgId;
UINT8 Flags;
UINT8 Reserved2[3];
} ACPI_ASF_INFO;
/* 1: ASF Alerts */
typedef struct acpi_asf_alert {
ACPI_ASF_HEADER_DEF
UINT8 AssertMask;
UINT8 DeassertMask;
UINT8 Alerts;
UINT8 DataLength;
UINT8 Array[1];
} ACPI_ASF_ALERT;
/* 2: ASF Remote Control */
typedef struct acpi_asf_remote {
ACPI_ASF_HEADER_DEF
UINT8 Controls;
UINT8 DataLength;
UINT16 Reserved2;
UINT8 Array[1];
} ACPI_ASF_REMOTE;
/* 3: ASF RMCP Boot Options */
typedef struct acpi_asf_rmcp {
ACPI_ASF_HEADER_DEF
UINT8 Capabilities[7];
UINT8 CompletionCode;
UINT32 EnterpriseId;
UINT8 Command;
UINT16 Parameter;
UINT16 BootOptions;
UINT16 OemParameters;
} ACPI_ASF_RMCP;
/* 4: ASF Address */
typedef struct acpi_asf_address {
ACPI_ASF_HEADER_DEF
UINT8 EpromAddress;
UINT8 Devices;
UINT8 SmbusAddresses[1];
} ACPI_ASF_ADDRESS;
/*******************************************************************************
*
* BOOT - Simple Boot Flag Table
*
******************************************************************************/
typedef struct acpi_table_boot {
ACPI_TABLE_HEADER_DEF
UINT8 CmosIndex; /* Index in CMOS RAM for the boot register */
UINT8 Reserved[3];
} ACPI_TABLE_BOOT;
/*******************************************************************************
*
* CPEP - Corrected Platform Error Polling table
*
******************************************************************************/
typedef struct acpi_table_cpep {
ACPI_TABLE_HEADER_DEF
UINT64 Reserved;
} ACPI_TABLE_CPEP;
/* Subtable */
typedef struct acpi_cpep_polling {
UINT8 Type;
UINT8 Length;
UINT8 ProcessorId; /* Processor ID */
UINT8 ProcessorEid; /* Processor EID */
UINT32 PollingInterval;/* Polling interval (msec) */
} ACPI_CPEP_POLLING;
/*******************************************************************************
*
* DBGP - Debug Port table
*
******************************************************************************/
typedef struct acpi_table_dbgp {
ACPI_TABLE_HEADER_DEF
UINT8 InterfaceType; /* 0=full 16550, 1=subset of 16550 */
UINT8 Reserved[3];
ACPI_GENERIC_ADDRESS DebugPort;
} ACPI_TABLE_DBGP;
/*******************************************************************************
*
* ECDT - Embedded Controller Boot Resources Table
*
******************************************************************************/
typedef struct ec_boot_resources {
ACPI_TABLE_HEADER_DEF
ACPI_GENERIC_ADDRESS EcControl; /* Address of EC command/status register */
ACPI_GENERIC_ADDRESS EcData; /* Address of EC data register */
UINT32 Uid; /* Unique ID - must be same as the EC _UID method */
UINT8 GpeBit; /* The GPE for the EC */
UINT8 EcId[1]; /* Full namepath of the EC in the ACPI namespace */
} EC_BOOT_RESOURCES;
/*******************************************************************************
*
* HPET - High Precision Event Timer table
*
******************************************************************************/
typedef struct acpi_hpet_table {
ACPI_TABLE_HEADER_DEF
UINT32 HardwareId; /* Hardware ID of event timer block */
ACPI_GENERIC_ADDRESS BaseAddress; /* Address of event timer block */
UINT8 HpetNumber; /* HPET sequence number */
UINT16 ClockTick; /* Main counter min tick, periodic mode */
UINT8 Attributes;
} HPET_TABLE;
#if 0 /* HPET flags to be converted to macros */
struct /* Flags (8 bits) */
{
UINT8 PageProtect :1;/* 00: No page protection */
UINT8 PageProtect4 :1;/* 01: 4KB page protected */
UINT8 PageProtect64 :1;/* 02: 64KB page protected */
UINT8 :5;/* 03-07: Reserved, must be zero */
} Flags;
#endif
/*******************************************************************************
*
* MADT - Multiple APIC Description Table
*
******************************************************************************/
typedef struct multiple_apic_table {
ACPI_TABLE_HEADER_DEF
UINT32 LocalApicAddress;/* Physical address of local APIC */
/* Flags (32 bits) */
UINT8 PCATCompat : 1;/* 00: System also has dual 8259s */
UINT8 : 7;/* 01-07: Reserved, must be zero */
UINT8 Reserved1[3]; /* 08-31: Reserved, must be zero */
} MULTIPLE_APIC_TABLE;
/* Values for MADT PCATCompat */
#define DUAL_PIC 0
#define MULTIPLE_APIC 1
/* Common MADT Sub-table header */
#define APIC_HEADER_DEF \
UINT8 Type; \
UINT8 Length;
typedef struct apic_header {
APIC_HEADER_DEF
} APIC_HEADER;
/* Values for Type in APIC_HEADER */
#define APIC_PROCESSOR 0
#define APIC_IO 1
#define APIC_XRUPT_OVERRIDE 2
#define APIC_NMI 3
#define APIC_LOCAL_NMI 4
#define APIC_ADDRESS_OVERRIDE 5
#define APIC_IO_SAPIC 6
#define APIC_LOCAL_SAPIC 7
#define APIC_XRUPT_SOURCE 8
#define APIC_RESERVED 9 /* 9 and greater are reserved */
/* Flag definitions for MADT sub-tables */
#define ACPI_MADT_IFLAGS /* INTI flags (16 bits) */ \
UINT8 Polarity : 2; /* 00-01: Polarity of APIC I/O input signals */ \
UINT8 TriggerMode : 2; /* 02-03: Trigger mode of APIC input signals */ \
UINT8 : 4; /* 04-07: Reserved, must be zero */ \
UINT8 Reserved1; /* 08-15: Reserved, must be zero */
#define ACPI_MADT_LFLAGS /* Local Sapic flags (32 bits) */ \
UINT8 ProcessorEnabled: 1; /* 00: Processor is usable if set */ \
UINT8 : 7; /* 01-07: Reserved, must be zero */ \
UINT8 Reserved2[3]; /* 08-31: Reserved, must be zero */
/* Values for MPS INTI flags */
#define POLARITY_CONFORMS 0
#define POLARITY_ACTIVE_HIGH 1
#define POLARITY_RESERVED 2
#define POLARITY_ACTIVE_LOW 3
#define TRIGGER_CONFORMS 0
#define TRIGGER_EDGE 1
#define TRIGGER_RESERVED 2
#define TRIGGER_LEVEL 3
/*
* MADT Sub-tables, correspond to Type in APIC_HEADER
*/
/* 0: processor APIC */
typedef struct madt_processor_apic {
APIC_HEADER_DEF
UINT8 ProcessorId; /* ACPI processor id */
UINT8 LocalApicId; /* Processor's local APIC id */
ACPI_MADT_LFLAGS
} MADT_PROCESSOR_APIC;
/* 1: IO APIC */
typedef struct madt_io_apic {
APIC_HEADER_DEF
UINT8 IoApicId; /* I/O APIC ID */
UINT8 Reserved; /* Reserved - must be zero */
UINT32 Address; /* APIC physical address */
UINT32 Interrupt; /* Global system interrupt where INTI lines start */
} MADT_IO_APIC;
/* 2: Interrupt Override */
typedef struct madt_interrupt_override {
APIC_HEADER_DEF
UINT8 Bus; /* 0 - ISA */
UINT8 Source; /* Interrupt source (IRQ) */
UINT32 Interrupt; /* Global system interrupt */
ACPI_MADT_IFLAGS
} MADT_INTERRUPT_OVERRIDE;
/* 3: NMI Sources */
typedef struct madt_nmi_source {
APIC_HEADER_DEF
ACPI_MADT_IFLAGS
UINT32 Interrupt; /* Global system interrupt */
} MADT_NMI_SOURCE;
/* 4: Local APIC NMI */
typedef struct madt_local_apic_nmi {
APIC_HEADER_DEF
UINT8 ProcessorId; /* ACPI processor id */
ACPI_MADT_IFLAGS
UINT8 Lint; /* LINTn to which NMI is connected */
} MADT_LOCAL_APIC_NMI;
/* 5: Address Override */
typedef struct madt_address_override {
APIC_HEADER_DEF
UINT16 Reserved; /* Reserved, must be zero */
UINT64 Address; /* APIC physical address */
} MADT_ADDRESS_OVERRIDE;
/* 6: I/O Sapic */
typedef struct madt_io_sapic {
APIC_HEADER_DEF
UINT8 IoSapicId; /* I/O SAPIC ID */
UINT8 Reserved; /* Reserved, must be zero */
UINT32 InterruptBase; /* Glocal interrupt for SAPIC start */
UINT64 Address; /* SAPIC physical address */
} MADT_IO_SAPIC;
/* 7: Local Sapic */
typedef struct madt_local_sapic {
APIC_HEADER_DEF
UINT8 ProcessorId; /* ACPI processor id */
UINT8 LocalSapicId; /* SAPIC ID */
UINT8 LocalSapicEid; /* SAPIC EID */
UINT8 Reserved[3]; /* Reserved, must be zero */
ACPI_MADT_LFLAGS
UINT32 ProcessorUID; /* Numeric UID - ACPI 3.0 */
char ProcessorUIDString[1];/* String UID - ACPI 3.0 */
} MADT_LOCAL_SAPIC;
/* 8: Platform Interrupt Source */
typedef struct madt_interrupt_source {
APIC_HEADER_DEF
ACPI_MADT_IFLAGS
UINT8 InterruptType; /* 1=PMI, 2=INIT, 3=corrected */
UINT8 ProcessorId; /* Processor ID */
UINT8 ProcessorEid; /* Processor EID */
UINT8 IoSapicVector; /* Vector value for PMI interrupts */
UINT32 Interrupt; /* Global system interrupt */
UINT32 Flags; /* Interrupt Source Flags */
} MADT_INTERRUPT_SOURCE;
/*******************************************************************************
*
* MCFG - PCI Memory Mapped Configuration table and sub-table
*
******************************************************************************/
typedef struct acpi_table_mcfg {
ACPI_TABLE_HEADER_DEF
UINT8 Reserved[8];
} ACPI_TABLE_MCFG;
typedef struct acpi_mcfg_allocation {
UINT64 BaseAddress; /* Base address, processor-relative */
UINT16 PciSegment; /* PCI segment group number */
UINT8 StartBusNumber; /* Starting PCI Bus number */
UINT8 EndBusNumber; /* Final PCI Bus number */
UINT32 Reserved;
} ACPI_MCFG_ALLOCATION;
/*******************************************************************************
*
* SBST - Smart Battery Specification Table
*
******************************************************************************/
typedef struct smart_battery_table {
ACPI_TABLE_HEADER_DEF
UINT32 WarningLevel;
UINT32 LowLevel;
UINT32 CriticalLevel;
} SMART_BATTERY_TABLE;
/*******************************************************************************
*
* SLIT - System Locality Distance Information Table
*
******************************************************************************/
typedef struct system_locality_info {
ACPI_TABLE_HEADER_DEF
UINT64 LocalityCount;
UINT8 Entry[1][1];
} SYSTEM_LOCALITY_INFO;
/*******************************************************************************
*
* SPCR - Serial Port Console Redirection table
*
******************************************************************************/
typedef struct acpi_table_spcr {
ACPI_TABLE_HEADER_DEF
UINT8 InterfaceType; /* 0=full 16550, 1=subset of 16550 */
UINT8 Reserved[3];
ACPI_GENERIC_ADDRESS SerialPort;
UINT8 InterruptType;
UINT8 PcInterrupt;
UINT32 Interrupt;
UINT8 BaudRate;
UINT8 Parity;
UINT8 StopBits;
UINT8 FlowControl;
UINT8 TerminalType;
UINT8 Reserved2;
UINT16 PciDeviceId;
UINT16 PciVendorId;
UINT8 PciBus;
UINT8 PciDevice;
UINT8 PciFunction;
UINT32 PciFlags;
UINT8 PciSegment;
UINT32 Reserved3;
} ACPI_TABLE_SPCR;
/*******************************************************************************
*
* SPMI - Server Platform Management Interface table
*
******************************************************************************/
typedef struct acpi_table_spmi {
ACPI_TABLE_HEADER_DEF
UINT8 Reserved;
UINT8 InterfaceType;
UINT16 SpecRevision; /* Version of IPMI */
UINT8 InterruptType;
UINT8 GpeNumber; /* GPE assigned */
UINT8 Reserved2;
UINT8 PciDeviceFlag;
UINT32 Interrupt;
ACPI_GENERIC_ADDRESS IpmiRegister;
UINT8 PciSegment;
UINT8 PciBus;
UINT8 PciDevice;
UINT8 PciFunction;
} ACPI_TABLE_SPMI;
/*******************************************************************************
*
* SRAT - System Resource Affinity Table
*
******************************************************************************/
typedef struct system_resource_affinity {
ACPI_TABLE_HEADER_DEF
UINT32 Reserved1; /* Must be value '1' */
UINT64 Reserved2; /* Reserved, must be zero */
} SYSTEM_RESOURCE_AFFINITY;
/* SRAT common sub-table header */
#define SRAT_SUBTABLE_HEADER \
UINT8 Type; \
UINT8 Length;
/* Values for Type above */
#define SRAT_CPU_AFFINITY 0
#define SRAT_MEMORY_AFFINITY 1
#define SRAT_RESERVED 2
/* SRAT sub-tables */
typedef struct static_resource_alloc {
SRAT_SUBTABLE_HEADER
UINT8 ProximityDomainLo;
UINT8 ApicId;
/* Flags (32 bits) */
UINT8 Enabled :1;/* 00: Use affinity structure */
UINT8 :7;/* 01-07: Reserved, must be zero */
UINT8 Reserved3[3]; /* 08-31: Reserved, must be zero */
UINT8 LocalSapicEid;
UINT8 ProximityDomainHi[3];
UINT32 Reserved4; /* Reserved, must be zero */
} STATIC_RESOURCE_ALLOC;
typedef struct memory_affinity {
SRAT_SUBTABLE_HEADER
UINT32 ProximityDomain;
UINT16 Reserved3;
UINT64 BaseAddress;
UINT64 AddressLength;
UINT32 Reserved4;
/* Flags (32 bits) */
UINT8 Enabled :1;/* 00: Use affinity structure */
UINT8 HotPluggable :1;/* 01: Memory region is hot pluggable */
UINT8 NonVolatile :1;/* 02: Memory is non-volatile */
UINT8 :5;/* 03-07: Reserved, must be zero */
UINT8 Reserved5[3]; /* 08-31: Reserved, must be zero */
UINT64 Reserved6; /* Reserved, must be zero */
} MEMORY_AFFINITY;
/*******************************************************************************
*
* TCPA - Trusted Computing Platform Alliance table
*
******************************************************************************/
typedef struct acpi_table_tcpa {
ACPI_TABLE_HEADER_DEF
UINT16 Reserved;
UINT32 MaxLogLength; /* Maximum length for the event log area */
UINT64 LogAddress; /* Address of the event log area */
} ACPI_TABLE_TCPA;
/*******************************************************************************
*
* WDRT - Watchdog Resource Table
*
******************************************************************************/
typedef struct acpi_table_wdrt {
ACPI_TABLE_HEADER_DEF
UINT32 HeaderLength; /* Watchdog Header Length */
UINT8 PciSegment; /* PCI Segment number */
UINT8 PciBus; /* PCI Bus number */
UINT8 PciDevice; /* PCI Device number */
UINT8 PciFunction; /* PCI Function number */
UINT32 TimerPeriod; /* Period of one timer count (msec) */
UINT32 MaxCount; /* Maximum counter value supported */
UINT32 MinCount; /* Minimum counter value */
UINT8 Flags;
UINT8 Reserved[3];
UINT32 Entries; /* Number of watchdog entries that follow */
} ACPI_TABLE_WDRT;
#if 0 /* Flags, will be converted to macros */
UINT8 Enabled :1; /* 00: Timer enabled */
UINT8 :6; /* 01-06: Reserved */
UINT8 SleepStop :1; /* 07: Timer stopped in sleep state */
#endif
/* Macros used to generate offsets to specific table fields */
#define ACPI_ASF0_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_ASF_INFO,f)
#define ACPI_ASF1_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_ASF_ALERT,f)
#define ACPI_ASF2_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_ASF_REMOTE,f)
#define ACPI_ASF3_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_ASF_RMCP,f)
#define ACPI_ASF4_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_ASF_ADDRESS,f)
#define ACPI_BOOT_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_TABLE_BOOT,f)
#define ACPI_CPEP_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_TABLE_CPEP,f)
#define ACPI_CPEP0_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_CPEP_POLLING,f)
#define ACPI_DBGP_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_TABLE_DBGP,f)
#define ACPI_ECDT_OFFSET(f) (UINT8) ACPI_OFFSET (EC_BOOT_RESOURCES,f)
#define ACPI_HPET_OFFSET(f) (UINT8) ACPI_OFFSET (HPET_TABLE,f)
#define ACPI_MADT_OFFSET(f) (UINT8) ACPI_OFFSET (MULTIPLE_APIC_TABLE,f)
#define ACPI_MADT0_OFFSET(f) (UINT8) ACPI_OFFSET (MADT_PROCESSOR_APIC,f)
#define ACPI_MADT1_OFFSET(f) (UINT8) ACPI_OFFSET (MADT_IO_APIC,f)
#define ACPI_MADT2_OFFSET(f) (UINT8) ACPI_OFFSET (MADT_INTERRUPT_OVERRIDE,f)
#define ACPI_MADT3_OFFSET(f) (UINT8) ACPI_OFFSET (MADT_NMI_SOURCE,f)
#define ACPI_MADT4_OFFSET(f) (UINT8) ACPI_OFFSET (MADT_LOCAL_APIC_NMI,f)
#define ACPI_MADT5_OFFSET(f) (UINT8) ACPI_OFFSET (MADT_ADDRESS_OVERRIDE,f)
#define ACPI_MADT6_OFFSET(f) (UINT8) ACPI_OFFSET (MADT_IO_SAPIC,f)
#define ACPI_MADT7_OFFSET(f) (UINT8) ACPI_OFFSET (MADT_LOCAL_SAPIC,f)
#define ACPI_MADT8_OFFSET(f) (UINT8) ACPI_OFFSET (MADT_INTERRUPT_SOURCE,f)
#define ACPI_MADTH_OFFSET(f) (UINT8) ACPI_OFFSET (APIC_HEADER,f)
#define ACPI_MCFG_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_TABLE_MCFG,f)
#define ACPI_MCFG0_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_MCFG_ALLOCATION,f)
#define ACPI_SBST_OFFSET(f) (UINT8) ACPI_OFFSET (SMART_BATTERY_TABLE,f)
#define ACPI_SLIT_OFFSET(f) (UINT8) ACPI_OFFSET (SYSTEM_LOCALITY_INFO,f)
#define ACPI_SPCR_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_TABLE_SPCR,f)
#define ACPI_SPMI_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_TABLE_SPMI,f)
#define ACPI_SRAT_OFFSET(f) (UINT8) ACPI_OFFSET (SYSTEM_RESOURCE_AFFINITY,f)
#define ACPI_SRAT0_OFFSET(f) (UINT8) ACPI_OFFSET (STATIC_RESOURCE_ALLOC,f)
#define ACPI_SRAT1_OFFSET(f) (UINT8) ACPI_OFFSET (MEMORY_AFFINITY,f)
#define ACPI_TCPA_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_TABLE_TCPA,f)
#define ACPI_WDRT_OFFSET(f) (UINT8) ACPI_OFFSET (ACPI_TABLE_WDRT,f)
#define ACPI_HPET_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (HPET_TABLE,f,o)
#define ACPI_SRAT0_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (STATIC_RESOURCE_ALLOC,f,o)
#define ACPI_SRAT1_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (MEMORY_AFFINITY,f,o)
#define ACPI_MADT_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (MULTIPLE_APIC_TABLE,f,o)
#define ACPI_MADT0_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (MADT_PROCESSOR_APIC,f,o)
#define ACPI_MADT2_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (MADT_INTERRUPT_OVERRIDE,f,o)
#define ACPI_MADT3_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (MADT_NMI_SOURCE,f,o)
#define ACPI_MADT4_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (MADT_LOCAL_APIC_NMI,f,o)
#define ACPI_MADT7_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (MADT_LOCAL_SAPIC,f,o)
#define ACPI_MADT8_FLAG_OFFSET(f, o) ACPI_FLAG_OFFSET (MADT_INTERRUPT_SOURCE,f,o)
/* Reset to default packing */
#pragma pack()
#endif /* __ACTBL1_H__ */

View file

@ -0,0 +1,36 @@
export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd
export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def
export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule
export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir
include $(MakeInc_cmd)
include $(MakeInc_def)
INSTINC_SUBDIRS =
INSTINC_SUBDIRS_X86_64 = \
i386
INSTINC_SUBDIRS_X86_64H = \
i386
INSTINC_SUBDIRS_ARM = \
arm
INSTINC_SUBDIRS_ARM64 = \
arm
EXPORT_FILES =
INSTALL_MI_LIST =
INSTALL_MI_DIR = architecture
INSTALL_KF_MI_LIST = byte_order.h
EXPORT_MI_LIST = ${EXPORT_FILES}
EXPORT_MI_DIR = architecture
include $(MakeInc_rule)
include $(MakeInc_dir)

View file

@ -0,0 +1,20 @@
export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd
export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def
export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule
export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir
include $(MakeInc_cmd)
include $(MakeInc_def)
EXPORT_FILES =
INSTALL_MD_LIST =
INSTALL_MD_DIR =
EXPORT_MD_LIST = ${EXPORT_FILES}
EXPORT_MD_DIR = architecture/arm
include $(MakeInc_rule)
include $(MakeInc_dir)

View file

@ -0,0 +1,371 @@
/*
* Copyright (c) 1999-2002 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License."
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1992 NeXT Computer, Inc.
*
* Byte ordering conversion.
*
*/
#ifndef _ARCHITECTURE_BYTE_ORDER_H_
#define _ARCHITECTURE_BYTE_ORDER_H_
#include <libkern/OSByteOrder.h>
typedef unsigned long NXSwappedFloat;
typedef unsigned long long NXSwappedDouble;
static __inline__
unsigned short
NXSwapShort(
unsigned short inv
)
{
return (unsigned short)OSSwapInt16((uint16_t)inv);
}
static __inline__
unsigned int
NXSwapInt(
unsigned int inv
)
{
return (unsigned int)OSSwapInt32((uint32_t)inv);
}
static __inline__
unsigned long
NXSwapLong(
unsigned long inv
)
{
return (unsigned long)OSSwapInt32((uint32_t)inv);
}
static __inline__
unsigned long long
NXSwapLongLong(
unsigned long long inv
)
{
return (unsigned long long)OSSwapInt64((uint64_t)inv);
}
static __inline__ NXSwappedFloat
NXConvertHostFloatToSwapped(float x)
{
union fconv {
float number;
NXSwappedFloat sf;
} u;
u.number = x;
return u.sf;
}
static __inline__ float
NXConvertSwappedFloatToHost(NXSwappedFloat x)
{
union fconv {
float number;
NXSwappedFloat sf;
} u;
u.sf = x;
return u.number;
}
static __inline__ NXSwappedDouble
NXConvertHostDoubleToSwapped(double x)
{
union dconv {
double number;
NXSwappedDouble sd;
} u;
u.number = x;
return u.sd;
}
static __inline__ double
NXConvertSwappedDoubleToHost(NXSwappedDouble x)
{
union dconv {
double number;
NXSwappedDouble sd;
} u;
u.sd = x;
return u.number;
}
static __inline__ NXSwappedFloat
NXSwapFloat(NXSwappedFloat x)
{
return (NXSwappedFloat)OSSwapInt32((uint32_t)x);
}
static __inline__ NXSwappedDouble
NXSwapDouble(NXSwappedDouble x)
{
return (NXSwappedDouble)OSSwapInt64((uint64_t)x);
}
/*
* Identify the byte order
* of the current host.
*/
enum NXByteOrder {
NX_UnknownByteOrder,
NX_LittleEndian,
NX_BigEndian
};
static __inline__
enum NXByteOrder
NXHostByteOrder(void)
{
#if defined(__LITTLE_ENDIAN__)
return NX_LittleEndian;
#elif defined(__BIG_ENDIAN__)
return NX_BigEndian;
#else
return NX_UnknownByteOrder;
#endif
}
static __inline__
unsigned short
NXSwapBigShortToHost(
unsigned short x
)
{
return (unsigned short)OSSwapBigToHostInt16((uint16_t)x);
}
static __inline__
unsigned int
NXSwapBigIntToHost(
unsigned int x
)
{
return (unsigned int)OSSwapBigToHostInt32((uint32_t)x);
}
static __inline__
unsigned long
NXSwapBigLongToHost(
unsigned long x
)
{
return (unsigned long)OSSwapBigToHostInt32((uint32_t)x);
}
static __inline__
unsigned long long
NXSwapBigLongLongToHost(
unsigned long long x
)
{
return (unsigned long long)OSSwapBigToHostInt64((uint64_t)x);
}
static __inline__
double
NXSwapBigDoubleToHost(
NXSwappedDouble x
)
{
return NXConvertSwappedDoubleToHost((NXSwappedDouble)OSSwapBigToHostInt64((uint64_t)x));
}
static __inline__
float
NXSwapBigFloatToHost(
NXSwappedFloat x
)
{
return NXConvertSwappedFloatToHost((NXSwappedFloat)OSSwapBigToHostInt32((uint32_t)x));
}
static __inline__
unsigned short
NXSwapHostShortToBig(
unsigned short x
)
{
return (unsigned short)OSSwapHostToBigInt16((uint16_t)x);
}
static __inline__
unsigned int
NXSwapHostIntToBig(
unsigned int x
)
{
return (unsigned int)OSSwapHostToBigInt32((uint32_t)x);
}
static __inline__
unsigned long
NXSwapHostLongToBig(
unsigned long x
)
{
return (unsigned long)OSSwapHostToBigInt32((uint32_t)x);
}
static __inline__
unsigned long long
NXSwapHostLongLongToBig(
unsigned long long x
)
{
return (unsigned long long)OSSwapHostToBigInt64((uint64_t)x);
}
static __inline__
NXSwappedDouble
NXSwapHostDoubleToBig(
double x
)
{
return (NXSwappedDouble)OSSwapHostToBigInt64((uint64_t)NXConvertHostDoubleToSwapped(x));
}
static __inline__
NXSwappedFloat
NXSwapHostFloatToBig(
float x
)
{
return (NXSwappedFloat)OSSwapHostToBigInt32((uint32_t)NXConvertHostFloatToSwapped(x));
}
static __inline__
unsigned short
NXSwapLittleShortToHost(
unsigned short x
)
{
return (unsigned short)OSSwapLittleToHostInt16((uint16_t)x);
}
static __inline__
unsigned int
NXSwapLittleIntToHost(
unsigned int x
)
{
return (unsigned int)OSSwapLittleToHostInt32((uint32_t)x);
}
static __inline__
unsigned long
NXSwapLittleLongToHost(
unsigned long x
)
{
return (unsigned long)OSSwapLittleToHostInt32((uint32_t)x);
}
static __inline__
unsigned long long
NXSwapLittleLongLongToHost(
unsigned long long x
)
{
return (unsigned long long)OSSwapLittleToHostInt64((uint64_t)x);
}
static __inline__
double
NXSwapLittleDoubleToHost(
NXSwappedDouble x
)
{
return NXConvertSwappedDoubleToHost((NXSwappedDouble)OSSwapLittleToHostInt64((uint64_t)x));
}
static __inline__
float
NXSwapLittleFloatToHost(
NXSwappedFloat x
)
{
return NXConvertSwappedFloatToHost((NXSwappedFloat)OSSwapLittleToHostInt32((uint32_t)x));
}
static __inline__
unsigned short
NXSwapHostShortToLittle(
unsigned short x
)
{
return (unsigned short)OSSwapHostToLittleInt16((uint16_t)x);
}
static __inline__
unsigned int
NXSwapHostIntToLittle(
unsigned int x
)
{
return (unsigned int)OSSwapHostToLittleInt32((uint32_t)x);
}
static __inline__
unsigned long
NXSwapHostLongToLittle(
unsigned long x
)
{
return (unsigned long)OSSwapHostToLittleInt32((uint32_t)x);
}
static __inline__
unsigned long long
NXSwapHostLongLongToLittle(
unsigned long long x
)
{
return (unsigned long long)OSSwapHostToLittleInt64((uint64_t)x);
}
static __inline__
NXSwappedDouble
NXSwapHostDoubleToLittle(
double x
)
{
return (NXSwappedDouble)OSSwapHostToLittleInt64((uint64_t)NXConvertHostDoubleToSwapped(x));
}
static __inline__
NXSwappedFloat
NXSwapHostFloatToLittle(
float x
)
{
return (NXSwappedFloat)OSSwapHostToLittleInt32((uint32_t)NXConvertHostFloatToSwapped(x));
}
#endif /* _ARCHITECTURE_BYTE_ORDER_H_ */

View file

@ -0,0 +1,29 @@
export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd
export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def
export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule
export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir
include $(MakeInc_cmd)
include $(MakeInc_def)
EXPORT_FILES = \
asm_help.h \
cpu.h \
io.h \
pio.h \
sel.h \
tss.h \
desc.h \
reg_help.h \
table.h
INSTALL_MD_LIST =
INSTALL_MD_DIR =
EXPORT_MD_LIST = ${EXPORT_FILES}
EXPORT_MD_DIR = architecture/i386
include $(MakeInc_rule)
include $(MakeInc_dir)

View file

@ -0,0 +1,413 @@
/*
* Copyright (c) 2021 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
*
* File: architecture/i386/asm_help.h
* Author: Mike DeMoney, NeXT Computer, Inc.
* Modified for i386 by: Bruce Martin, NeXT Computer, Inc.
*
* This header file defines macros useful when writing assembly code
* for the Intel i386 family processors.
*
* HISTORY
* 10-Mar-92 Bruce Martin (bmartin@next.com)
* Adapted to i386
* 23-Jan-91 Mike DeMoney (mike@next.com)
* Created.
*/
#ifndef _ARCH_I386_ASM_HELP_H_
#define _ARCH_I386_ASM_HELP_H_
#include <architecture/i386/reg_help.h>
#ifdef __ASSEMBLER__
/* Unwind Prologue added to each function to indicate the start of the unwind information. */
#define UNWIND_PROLOGUE \
.cfi_sections .eh_frame ;\
.cfi_startproc ;
/* Unwind Epilogue added to each function to indicate the end of the unwind information */
#define UNWIND_EPILOGUE .cfi_endproc
#define ALIGN \
.align 2, 0x90
#define ROUND_TO_STACK(len) \
(((len) + STACK_INCR - 1) / STACK_INCR * STACK_INCR)
#ifdef notdef
#if defined(__i386__)
#define CALL_MCOUNT \
pushl %ebp ;\
movl %esp, %ebp ;\
.data ;\
1: .long 0 ;\
.text ;\
lea 9b,%edx ;\
call mcount ;\
popl %ebp ;
#elif defined(__x86_64__)
#define CALL_MCOUNT \
pushq %rbp ;\
movq %rsp, %rbp ;\
.data ;\
1: .quad 0 ;\
.text ;\
lea 9b,%r13 ;\
call mcount ;\
popq %rbp ;
#endif
#else
#define CALL_MCOUNT
#endif
/*
* Prologue for functions that may call other functions. Saves
* registers and sets up a C frame.
*/
#if defined(__i386__)
#define NESTED_FUNCTION_PROLOGUE(localvarsize) \
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 1 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushl %ebp ;\
movl %esp, %ebp ;\
subl $L__framesize, %esp ;\
.endif ;\
pushl %edi ;\
pushl %esi ;\
pushl %ebx
#elif defined(__x86_64__)
#define NESTED_FUNCTION_PROLOGUE(localvarsize) \
UNWIND_PROLOGUE ;\
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 1 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushq %rbp ;\
movq %rsp, %rbp ;\
subq $L__framesize, %rsp ;\
.endif ;
#endif
/*
* Prologue for functions that do not call other functions. Does not
* save registers (this is the functions responsibility). Does set
* up a C frame.
*/
#if defined(__i386__)
#define LEAF_FUNCTION_PROLOGUE(localvarsize) \
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 0 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushl %ebp ;\
movl %esp, %ebp ;\
subl $L__framesize, %esp ;\
.endif
#elif defined(__x86_64__)
#define LEAF_FUNCTION_PROLOGUE(localvarsize) \
UNWIND_PROLOGUE ;\
.set L__framesize,ROUND_TO_STACK(localvarsize) ;\
.set L__nested_function, 0 ;\
CALL_MCOUNT \
.if L__framesize ;\
pushq %rbp ;\
movq %rsp, %rbp ;\
subq $L__framesize, %rsp ;\
.endif
#endif
/*
* Epilogue for any function.
*
* We assume that all Leaf functions will be responsible for saving any
* local registers they clobber.
*/
#if defined(__i386__)
#define FUNCTION_EPILOGUE \
.if L__nested_function ;\
popl %ebx ;\
popl %esi ;\
popl %edi ;\
.endif ;\
.if L__framesize ;\
movl %ebp, %esp ;\
popl %ebp ;\
.endif ;\
ret
#elif defined(__x86_64__)
#define FUNCTION_EPILOGUE \
.if L__framesize ;\
movq %rbp, %rsp ;\
popq %rbp ;\
.endif ;\
ret ;\
UNWIND_EPILOGUE
#endif
/*
* Macros for declaring procedures
*
* Use of these macros allows ctags to have a predictable way
* to find various types of declarations. They also simplify
* inserting appropriate symbol table information.
*
* NOTE: these simple stubs will be replaced with more
* complicated versions once we know what the linker and gdb
* will require as far as register use masks and frame declarations.
* These macros may also be ifdef'ed in the future to contain profiling
* code.
*
*/
/*
* TEXT -- declare start of text segment
*/
#define TEXT \
.text
/*
* DATA -- declare start of data segment
*/
#define DATA \
.data
/*
* LEAF -- declare global leaf procedure
* NOTE: Control SHOULD NOT FLOW into a LEAF! A LEAF should only
* be jumped to. (A leaf may do an align.) Use a LABEL() if you
* need control to flow into the label.
*/
#define LEAF(name, localvarsize) \
.globl name ;\
ALIGN ;\
name: ;\
LEAF_FUNCTION_PROLOGUE(localvarsize)
/*
* X_LEAF -- declare alternate global label for leaf
*/
#define X_LEAF(name, value) \
.globl name ;\
.set name,value
/*
* P_LEAF -- declare private leaf procedure
*/
#define P_LEAF(name, localvarsize) \
ALIGN ;\
name: ;\
LEAF_FUNCTION_PROLOGUE(localvarsize)
/*
* LABEL -- declare a global code label
* MUST be used (rather than LEAF, NESTED, etc) if control
* "flows into" the label.
*/
#define LABEL(name) \
.globl name ;\
name:
/*
* NESTED -- declare procedure that invokes other procedures
*/
#define NESTED(name, localvarsize) \
.globl name ;\
ALIGN ;\
name: ;\
NESTED_FUNCTION_PROLOGUE(localvarsize)
/*
* X_NESTED -- declare alternate global label for nested proc
*/
#define X_NESTED(name, value) \
.globl name ;\
.set name,value
/*
* P_NESTED -- declare private nested procedure
*/
#define P_NESTED(name, localvarsize) \
ALIGN ;\
name: ;\
NESTED_FUNCTION_PROLOGUE(localvarsize)
/*
* END -- mark end of procedure
*/
#define END(name) \
FUNCTION_EPILOGUE
/*
* Storage definition macros
* The main purpose of these is to allow an easy handle for ctags
*/
/*
* IMPORT -- import symbol
*/
#define IMPORT(name) \
.reference name
/*
* ABS -- declare global absolute symbol
*/
#define ABS(name, value) \
.globl name ;\
.set name,value
/*
* P_ABS -- declare private absolute symbol
*/
#define P_ABS(name, value) \
.set name,value
/*
* EXPORT -- declare global label for data
*/
#define EXPORT(name) \
.globl name ;\
name:
/*
* BSS -- declare global zero'ed storage
*/
#define BSS(name,size) \
.comm name,size
/*
* P_BSS -- declare private zero'ed storage
*/
#define P_BSS(name,size) \
.lcomm name,size
/*
* dynamic/PIC macros for routines which reference external symbols
*/
#if defined(__DYNAMIC__)
#if defined(__i386__)
#define PICIFY(var) \
call 1f ; \
1: ; \
popl %edx ; \
movl L ## var ## __non_lazy_ptr-1b(%edx),%edx
#elif defined(__x86_64__)
#define PICIFY(var) \
movq var@GOTPCREL(%rip),%r11
#endif
#if defined(__i386__)
#define CALL_EXTERN_AGAIN(func) \
PICIFY(func) ; \
call *%edx
#elif defined(__x86_64__)
#define CALL_EXTERN_AGAIN(func) \
call func
#endif
#if defined(__i386__)
#define NON_LAZY_STUB(var) \
.section __IMPORT,__pointers,non_lazy_symbol_pointers ; \
L ## var ## __non_lazy_ptr: ; \
.indirect_symbol var ; \
.long 0 ; \
.text
#elif defined(__x86_64__)
#define NON_LAZY_STUB(var)
#endif
#define CALL_EXTERN(func) \
CALL_EXTERN_AGAIN(func) ; \
NON_LAZY_STUB(func)
#if defined(__i386__)
#define BRANCH_EXTERN(func) \
PICIFY(func) ; \
jmp *%edx ; \
NON_LAZY_STUB(func)
#elif defined(__x86_64__)
#define BRANCH_EXTERN(func) \
jmp func
#endif
#if defined(__i386__)
#define PUSH_EXTERN(var) \
PICIFY(var) ; \
movl (%edx),%edx ; \
pushl %edx ; \
NON_LAZY_STUB(var)
#endif
#if defined(__i386__)
#define REG_TO_EXTERN(reg, var) \
PICIFY(var) ; \
movl reg, (%edx) ; \
NON_LAZY_STUB(var)
#elif defined(__x86_64__)
#define REG_TO_EXTERN(reg, var) \
PICIFY(var) ; \
mov reg, (%r11)
#endif
#if defined(__i386__)
#define EXTERN_TO_REG(var, reg) \
call 1f ; \
1: ; \
popl %edx ; \
movl L ## var ##__non_lazy_ptr-1b(%edx),reg ; \
NON_LAZY_STUB(var)
#elif defined(__x86_64__)
#define EXTERN_TO_REG(var, reg) \
PICIFY(var) ; \
mov (%r11), reg
#endif
#else
#define BRANCH_EXTERN(func) jmp func
#define PUSH_EXTERN(var) push var
#define CALL_EXTERN(func) call func
#define CALL_EXTERN_AGAIN(func) call func
#if defined(__i386__)
#define REG_TO_EXTERN(reg, var) mov reg, var
#define EXTERN_TO_REG(var, reg) mov $ ## var, reg
#elif defined(__x86_64__)
#define REG_TO_EXTERN(reg, var) mov reg, var ## (%rip)
#define EXTERN_TO_REG(var, reg) mov var ## (%rip), reg
#endif
#endif
#endif /* __ASSEMBLER__ */
#endif /* _ARCH_I386_ASM_HELP_H_ */

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1992 NeXT Computer, Inc.
*
* Intel386 Family: Special processor registers.
*
* HISTORY
*
* 5 April 1992 ? at NeXT
* Created.
*/
/*
* Control register 0
*/
typedef struct _cr0 {
unsigned int pe :1,
mp :1,
em :1,
ts :1,
:1,
ne :1,
:10,
wp :1,
:1,
am :1,
:10,
nw :1,
cd :1,
pg :1;
} cr0_t;

View file

@ -0,0 +1,151 @@
/*
* Copyright (c) 2000-2019 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1992 NeXT Computer, Inc.
*
* Intel386 Family: Segment descriptors.
*
* HISTORY
*
* 29 March 1992 ? at NeXT
* Created.
*/
/*
* Code segment descriptor.
*/
typedef struct code_desc {
unsigned short limit00;
unsigned short base00;
unsigned char base16;
unsigned char type :5,
#define DESC_CODE_EXEC 0x18
#define DESC_CODE_READ 0x1a
dpl :2,
present :1;
unsigned char limit16 :4,
:1,
Lflag :1,
opsz :1,
#define DESC_CODE_16B 0
#define DESC_CODE_32B 1
granular:1;
#define DESC_GRAN_BYTE 0
#define DESC_GRAN_PAGE 1
unsigned char base24;
} code_desc_t;
/*
* Data segment descriptor.
*/
typedef struct data_desc {
unsigned short limit00;
unsigned short base00;
unsigned char base16;
unsigned char type :5,
#define DESC_DATA_RONLY 0x10
#define DESC_DATA_WRITE 0x12
dpl :2,
present :1;
unsigned char limit16 :4,
:2,
stksz :1,
#define DESC_DATA_16B 0
#define DESC_DATA_32B 1
granular:1;
unsigned char base24;
} data_desc_t;
/*
* LDT segment descriptor.
*/
typedef struct ldt_desc {
unsigned short limit00;
unsigned short base00;
unsigned char base16;
unsigned char type :5,
#define DESC_LDT 0x02
:2,
present :1;
unsigned char limit16 :4,
:3,
granular:1;
unsigned char base24;
} ldt_desc_t;
#include <architecture/i386/sel.h>
/*
* Call gate descriptor.
*/
typedef struct call_gate {
unsigned short offset00;
sel_t seg;
unsigned int argcnt :5,
:3,
type :5,
#define DESC_CALL_GATE 0x0c
dpl :2,
present :1,
offset16:16;
} call_gate_t;
/*
* Trap gate descriptor.
*/
typedef struct trap_gate {
unsigned short offset00;
sel_t seg;
unsigned int :8,
type :5,
#define DESC_TRAP_GATE 0x0f
dpl :2,
present :1,
offset16:16;
} trap_gate_t;
/*
* Interrupt gate descriptor.
*/
typedef struct intr_gate {
unsigned short offset00;
sel_t seg;
unsigned int :8,
type :5,
#define DESC_INTR_GATE 0x0e
dpl :2,
present :1,
offset16:16;
} intr_gate_t;

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1992 NeXT Computer, Inc.
*
* Intel 386 Family: IO space defines.
*
* HISTORY
*
* 11 August 1992 ? at NeXT
* Created.
*/
typedef unsigned short io_addr_t;
typedef unsigned short io_len_t;

View file

@ -0,0 +1,109 @@
/*
* Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
#ifndef _ARCH_I386_PIO_H_
#define _ARCH_I386_PIO_H_
typedef unsigned short i386_ioport_t;
#if defined(__GNUC__)
static __inline__ unsigned int inl(
i386_ioport_t port)
{
unsigned int datum;
__asm__ volatile("inl %w1, %0" : "=a" (datum) : "Nd" (port));
return(datum);
}
static __inline__ unsigned short inw(
i386_ioport_t port)
{
unsigned short datum;
__asm__ volatile("inw %w1, %w0" : "=a" (datum) : "Nd" (port));
return(datum);
}
static __inline__ unsigned char inb(
i386_ioport_t port)
{
unsigned char datum;
__asm__ volatile("inb %w1, %b0" : "=a" (datum) : "Nd" (port));
return(datum);
}
static __inline__ void outl(
i386_ioport_t port,
unsigned int datum)
{
__asm__ volatile("outl %0, %w1" : : "a" (datum), "Nd" (port));
}
static __inline__ void outw(
i386_ioport_t port,
unsigned short datum)
{
__asm__ volatile("outw %w0, %w1" : : "a" (datum), "Nd" (port));
}
static __inline__ void outb(
i386_ioport_t port,
unsigned char datum)
{
__asm__ volatile("outb %b0, %w1" : : "a" (datum), "Nd" (port));
}
#endif /* defined(__GNUC__) */
#endif /* _ARCH_I386_PIO_H_ */

View file

@ -0,0 +1,110 @@
/*
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
*
* File: architecture/i386/reg_help.h
* Author: Mike DeMoney, NeXT Computer, Inc.
* Modified for i386 by: Bruce Martin, NeXT Computer, Inc.
*
* This header file defines cpp macros useful for defining
* machine register and doing machine-level operations.
*
* HISTORY
* 10-Mar-92 Bruce Martin (bmartin@next.com)
* Adapted to i386
* 23-Jan-91 Mike DeMoney (mike@next.com)
* Created.
*/
#ifndef _ARCH_I386_REG_HELP_H_
#define _ARCH_I386_REG_HELP_H_
/* Bitfield definition aid */
#define BITS_WIDTH(msb, lsb) ((msb)-(lsb)+1)
#define BIT_WIDTH(pos) (1) /* mostly to record the position */
/* Mask creation */
#define MKMASK(width, offset) (((unsigned)-1)>>(32-(width))<<(offset))
#define BITSMASK(msb, lsb) MKMASK(BITS_WIDTH(msb, lsb), lsb & 0x1f)
#define BITMASK(pos) MKMASK(BIT_WIDTH(pos), pos & 0x1f)
/* Register addresses */
#if __ASSEMBLER__
# define REG_ADDR(type, addr) (addr)
#else /* __ASSEMBLER__ */
# define REG_ADDR(type, addr) (*(volatile type *)(addr))
#endif /* __ASSEMBLER__ */
/* Cast a register to be an unsigned */
#define CONTENTS(foo) (*(unsigned *) &(foo))
/* Stack pointer must always be a multiple of 4 */
#define STACK_INCR 4
#define ROUND_FRAME(x) ((((unsigned)(x)) + STACK_INCR - 1) & ~(STACK_INCR-1))
/* STRINGIFY -- perform all possible substitutions, then stringify */
#define __STR(x) #x /* just a helper macro */
#define STRINGIFY(x) __STR(x)
/*
* REG_PAIR_DEF -- define a register pair
* Register pairs are appropriately aligned to allow access via
* ld.d and st.d.
*
* Usage:
* struct foo {
* REG_PAIR_DEF(
* bar_t *, barp,
* afu_t, afu
* );
* };
*
* Access to individual entries of the pair is via the REG_PAIR
* macro (below).
*/
#define REG_PAIR_DEF(type0, name0, type1, name1) \
struct { \
type0 name0 __attribute__(( aligned(8) )); \
type1 name1; \
} name0##_##name1
/*
* REG_PAIR -- Macro to define names for accessing individual registers
* of register pairs.
*
* Usage:
* arg0 is first element of pair
* arg1 is second element of pair
* arg2 is desired element of pair
* eg:
* #define foo_barp REG_PAIR(barp, afu, afu)
*/
#define REG_PAIR(name0, name1, the_name) \
name0##_##name1.the_name
#endif /* _ARCH_I386_REG_HELP_H_ */

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1992 NeXT Computer, Inc.
*
* Intel386 Family: Segment selector.
*
* HISTORY
*
* 29 March 1992 ? at NeXT
* Created.
*/
/*
* Segment selector.
*/
#ifndef __XNU_ARCH_I386_SEL_H
#define __XNU_ARCH_I386_SEL_H
typedef struct sel {
unsigned short rpl :2,
#define KERN_PRIV 0
#define USER_PRIV 3
ti :1,
#define SEL_GDT 0
#define SEL_LDT 1
index :13;
} sel_t;
#define NULL_SEL ((sel_t) { 0, 0, 0 } )
#endif /* __XNU_ARCH_I386_SEL_H */

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1992 NeXT Computer, Inc.
*
* Intel386 Family: Descriptor tables.
*
* HISTORY
*
* 30 March 1992 ? at NeXT
* Created.
*/
#include <architecture/i386/desc.h>
#include <architecture/i386/tss.h>
/*
* A totally generic descriptor
* table entry.
*/
typedef union dt_entry {
code_desc_t code;
data_desc_t data;
ldt_desc_t ldt;
tss_desc_t task_state;
call_gate_t call_gate;
trap_gate_t trap_gate;
intr_gate_t intr_gate;
task_gate_t task_gate;
} dt_entry_t;
#define DESC_TBL_MAX 8192
/*
* Global descriptor table.
*/
typedef union gdt_entry {
code_desc_t code;
data_desc_t data;
ldt_desc_t ldt;
call_gate_t call_gate;
task_gate_t task_gate;
tss_desc_t task_state;
} gdt_entry_t;
typedef gdt_entry_t gdt_t;
/*
* Interrupt descriptor table.
*/
typedef union idt_entry {
trap_gate_t trap_gate;
intr_gate_t intr_gate;
task_gate_t task_gate;
} idt_entry_t;
typedef idt_entry_t idt_t;
/*
* Local descriptor table.
*/
typedef union ldt_entry {
code_desc_t code;
data_desc_t data;
call_gate_t call_gate;
task_gate_t task_gate;
} ldt_entry_t;
typedef ldt_entry_t ldt_t;

View file

@ -0,0 +1,120 @@
/*
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1992 NeXT Computer, Inc.
*
* Intel386 Family: Task State Segment.
*
* HISTORY
*
* 29 March 1992 ? at NeXT
* Created.
*/
#include <architecture/i386/sel.h>
/*
* Task State segment.
*/
typedef struct tss {
sel_t oldtss;
unsigned int :0;
unsigned int esp0;
sel_t ss0;
unsigned int :0;
unsigned int esp1;
sel_t ss1;
unsigned int :0;
unsigned int esp2;
sel_t ss2;
unsigned int :0;
unsigned int cr3;
unsigned int eip;
unsigned int eflags;
unsigned int eax;
unsigned int ecx;
unsigned int edx;
unsigned int ebx;
unsigned int esp;
unsigned int ebp;
unsigned int esi;
unsigned int edi;
sel_t es;
unsigned int :0;
sel_t cs;
unsigned int :0;
sel_t ss;
unsigned int :0;
sel_t ds;
unsigned int :0;
sel_t fs;
unsigned int :0;
sel_t gs;
unsigned int :0;
sel_t ldt;
unsigned int :0;
unsigned int t :1,
:15,
io_bmap :16;
} tss_t;
#define TSS_SIZE(n) (sizeof (struct tss) + (n))
/*
* Task State segment descriptor.
*/
typedef struct tss_desc {
unsigned short limit00;
unsigned short base00;
unsigned char base16;
unsigned char type :5,
#define DESC_TSS 0x09
dpl :2,
present :1;
unsigned char limit16 :4,
:3,
granular:1;
unsigned char base24;
} tss_desc_t;
/*
* Task gate descriptor.
*/
typedef struct task_gate {
unsigned short :16;
sel_t tss;
unsigned int :8,
type :5,
#define DESC_TASK_GATE 0x05
dpl :2,
present :1,
:0;
} task_gate_t;

View file

@ -0,0 +1,246 @@
/* Copyright (c) (2010-2012,2014-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CC_H_
#define _CORECRYPTO_CC_H_
#include <corecrypto/cc_config.h>
#include <corecrypto/cc_impl.h>
#include <corecrypto/cc_error.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdarg.h>
CC_PTRCHECK_CAPABLE_HEADER()
#if __has_feature(attribute_availability_with_replacement)
#if __has_feature(attribute_availability_bridgeos)
#ifndef __CC_BRIDGE_OS_DEPRECATED
#define __CC_BRIDGEOS_DEPRECATED(_dep, _msg) __attribute__((availability(bridgeos,deprecated=_dep, replacement=_msg)))
#endif
#endif
#ifndef __CC_BRIDGEOS_DEPRECATED
#define __CC_BRIDGEOS_DEPRECATED(_dep, _msg)
#endif
#define cc_deprecate_with_replacement(replacement_message, ios_version, macos_version, tvos_version, watchos_version, bridgeos_version) \
__attribute__((availability(macos,deprecated=macos_version, replacement=replacement_message)))\
__attribute__((availability(ios,deprecated=ios_version, replacement=replacement_message)))\
__attribute__((availability(watchos,deprecated=watchos_version, replacement=replacement_message)))\
__attribute__((availability(tvos,deprecated=tvos_version, replacement=replacement_message)))\
__CC_BRIDGEOS_DEPRECATED(bridgeos_version, replacement_message)
#define cc_unavailable() \
__attribute__((availability(macos,unavailable)))\
__attribute__((availability(ios,unavailable)))\
__attribute__((availability(watchos,unavailable)))\
__attribute__((availability(tvos,unavailable)))\
__attribute__((availability(bridgeos,unavailable)))
#if CC_PTRCHECK
#define cc_ptrcheck_unavailable() cc_unavailable()
#else
#define cc_ptrcheck_unavailable()
#endif
#else /* !__has_feature(attribute_availability_with_replacement) */
#define cc_deprecate_with_replacement(replacement_message, ios_version, macos_version, tvos_version, watchos_version, bridgeos_version)
#define cc_unavailable()
#define cc_ptrcheck_unavailable()
#endif /* __has_feature(attribute_availability_with_replacement) */
/* Provide a general purpose macro concat method. */
#define cc_concat_(a, b) a##b
#define cc_concat(a, b) cc_concat_(a, b)
#if defined(_MSC_VER)
#define __asm__(x)
#endif
/* Manage asserts here because a few functions in header public files do use asserts */
#if CORECRYPTO_DEBUG
#define cc_assert(x) assert(x)
#else
#define cc_assert(x)
#endif
#if CC_KERNEL
#include <kern/assert.h>
#else
#include <assert.h>
#endif
/* Provide a static assert that can be used to create compile-type failures. */
#if __has_feature(c_static_assert) || __has_extension(c_static_assert)
#define cc_static_assert(e, m) _Static_assert(e, m)
#elif !defined(__GNUC__)
#define cc_static_assert(e, m) enum { cc_concat(static_assert_, __COUNTER__) = 1 / (int)(!!(e)) }
#else
#define cc_static_assert(e, m)
#endif
/* Declare a struct element with a guarenteed alignment of _alignment_.
The resulting struct can be used to create arrays that are aligned by
a certain amount. */
#define cc_aligned_struct(_alignment_) \
typedef struct { \
uint8_t b[_alignment_]; \
} CC_ALIGNED(_alignment_)
#if defined(__BIGGEST_ALIGNMENT__)
#define CC_MAX_ALIGNMENT ((size_t)__BIGGEST_ALIGNMENT__)
#else
#define CC_MAX_ALIGNMENT ((size_t)16)
#endif
/* pads a given size to be a multiple of the biggest alignment for any type */
#define cc_pad_align(_size_) ((_size_ + CC_MAX_ALIGNMENT - 1) & (~(CC_MAX_ALIGNMENT - 1)))
/* number of array elements used in a cc_ctx_decl */
#define cc_ctx_n(_type_, _size_) ((_size_ + sizeof(_type_) - 1) / sizeof(_type_))
/* sizeof of a context declared with cc_ctx_decl */
#define cc_ctx_sizeof(_type_, _size_) sizeof(_type_[cc_ctx_n(_type_, _size_)])
// VLA warning opt-outs to help transition away from VLAs.
#if defined(__KEIL__)
#define CC_IGNORE_VLA_WARNINGS \
#pragma push \
#pragma diag_suppress 1057
#define CC_RESTORE_VLA_WARNINGS \
#pragma pop
#else
#define CC_IGNORE_VLA_WARNINGS \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wvla\"")
#define CC_RESTORE_VLA_WARNINGS \
_Pragma("GCC diagnostic pop")
#endif
/*
1. _alloca cannot be removed because this header file is compiled with both MSVC++ and with clang.
2. The _MSC_VER version of cc_ctx_decl() is not compatible with the way *_decl macros as used in CommonCrypto, AppleKeyStore and SecurityFrameworks. To observe the incompatibilities and errors, use below definition. Corecrypto itself, accepts both definitions
#define cc_ctx_decl(_type_, _size_, _name_) _type_ _name_ ## _array[cc_ctx_n(_type_, (_size_))]; _type_ *_name_ = _name_ ## _array
3. Never use sizeof() operator for the variables declared with cc_ctx_decl(), because it is not be compatible with the _MSC_VER version of cc_ctx_decl().
*/
#if defined(_MSC_VER)
#include <malloc.h>
#define cc_ctx_decl(_type_, _size_, _name_) _type_ * _name_ = (_type_ *) _alloca(sizeof(_type_) * cc_ctx_n(_type_, _size_) )
#else
// Enable VLA warnings for internal uses of cc_ctx_decl().
#if defined(DISABLE_INTERNAL_VLAS) && DISABLE_INTERNAL_VLAS
#define cc_ctx_decl(_type_, _size_, _name_) \
_type_ _name_ [cc_ctx_n(_type_, _size_)];
#else
#define cc_ctx_decl(_type_, _size_, _name_) \
CC_IGNORE_VLA_WARNINGS \
_type_ _name_ [cc_ctx_n(_type_, _size_)]; \
CC_RESTORE_VLA_WARNINGS
#endif // DISABLE_INTERNAL_VLAS
#endif // defined(_MSC_VER)
#define cc_ctx_decl_field(_type_, _size_, _name_) \
_type_ _name_ [cc_ctx_n(_type_, _size_)]
// VLA warning opt-outs to help transition away from VLAs.
#define cc_ctx_decl_vla(_type_, _size_, _name_) \
CC_IGNORE_VLA_WARNINGS \
cc_ctx_decl(_type_, _size_, _name_); \
CC_RESTORE_VLA_WARNINGS
/*!
@brief cc_clear(len, dst) zeroizes array dst and it will not be optimized out.
@discussion It is used to clear sensitive data, particularly when the are defined in the stack
@param len number of bytes to be cleared in dst
@param dst input array
*/
CC_NONNULL((2))
void cc_clear(size_t len, void *cc_sized_by(len) dst);
#define cc_copy(_size_, _dst_, _src_) memcpy(_dst_, _src_, _size_)
CC_INLINE CC_NONNULL((2))
void cc_xor(size_t size, void *cc_sized_by(size) r, const void *cc_sized_by(size) s, const void *cc_sized_by(size) t) {
uint8_t *_r=(uint8_t *)r;
const uint8_t *_s=(const uint8_t *)s;
const uint8_t *_t=(const uint8_t *)t;
size_t _size = size;
while (_size--) {
_r[_size] = _s[_size] ^ _t[_size];
}
}
/*!
@brief cc_cmp_safe(num, pt1, pt2) compares two array ptr1 and ptr2 of num bytes.
@discussion The execution time/cycles is independent of the data and therefore guarantees no leak about the data. However, the execution time depends on num.
@param num number of bytes in each array
@param ptr1 input array
@param ptr2 input array
@return returns 0 if the num bytes starting at ptr1 are identical to the num bytes starting at ptr2 and 1 if they are different or if num is 0 (empty arrays).
*/
CC_NONNULL((2, 3))
int cc_cmp_safe (size_t num, const void * cc_sized_by(num) ptr1, const void * cc_sized_by(num) ptr2);
/* Exchange S and T of any value type.
NOTE: S and T are evaluated multiple times and MUST NOT be expressions. */
#define CC_SWAP(S, T) do { \
S ^= T; T ^= S; S ^= T; \
} while (0)
/* Return the maximum value between S and T. */
#define CC_MAX(S, T) ({__typeof__(S) _cc_max_s = S; __typeof__(T) _cc_max_t = T; _cc_max_s > _cc_max_t ? _cc_max_s : _cc_max_t;})
/* Clone of CC_MAX() that evalutes S and T multiple times to allow nesting. */
#define CC_MAX_EVAL(S, T) ((S) > (T) ? (S) : (T))
/* Return the minimum value between S and T. */
#define CC_MIN(S, T) ({__typeof__(S) _cc_min_s = S; __typeof__(T) _cc_min_t = T; _cc_min_s <= _cc_min_t ? _cc_min_s : _cc_min_t;})
/* Clone of CC_MIN() that evalutes S and T multiple times to allow nesting. */
#define CC_MIN_EVAL(S, T) ((S) < (T) ? (S) : (T))
/*
When building with "-nostdinc" (i.e. iboot), ptrauth.h is in a non-standard location.
This requires a new flag to be used when building iboot: -ibuiltininc which is not
yet available.
*/
#if __has_feature(ptrauth_calls) && (CC_KERNEL || CC_USE_L4 || CC_USE_SEPROM)
#include <ptrauth.h>
#define CC_SPTR(_sn_, _n_) \
__ptrauth(ptrauth_key_process_independent_code, 1, ptrauth_string_discriminator("cc_" #_sn_ #_n_)) _n_
#else
#define CC_SPTR(_sn_, _n_) _n_
#endif
// Similar to the iovec type used in scatter-gather APIs like readv()
// and writev().
typedef struct cc_iovec {
const void *base;
size_t nbytes;
} cc_iovec_t;
#endif /* _CORECRYPTO_CC_H_ */

View file

@ -0,0 +1,820 @@
/* Copyright (c) (2010-2023) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CC_CONFIG_H_
#define _CORECRYPTO_CC_CONFIG_H_
/* A word about configuration macros:
Conditional configuration macros specific to corecrypto should be named CORECRYPTO_xxx
or CCxx_yyy and be defined to be either 0 or 1 in this file. You can add an
#ifndef #error construct at the end of this file to make sure it's always defined.
They should always be tested using the #if directive, never the #ifdef directive.
No other conditional macros shall ever be used (except in this file)
Configuration Macros that are defined outside of corecrypto (eg: KERNEL, DEBUG, ...)
shall only be used in this file to define CCxxx macros.
External macros should be assumed to be either undefined, defined with no value,
or defined as true or false. We shall strive to build with -Wundef whenever possible,
so the following construct should be used to test external macros in this file:
#if defined(DEBUG) && (DEBUG)
#define CORECRYPTO_DEBUG 1
#else
#define CORECRYPTO_DEBUG 0
#endif
It is acceptable to define a conditional CC_xxxx macro in an implementation file,
to be used only in this file.
The current code is not guaranteed to follow those rules, but should be fixed to.
Corecrypto requires GNU and C99 compatibility.
Typically enabled by passing --gnu --c99 to the compiler (eg. armcc)
*/
#if !defined(__has_feature)
#define __has_feature(FEATURE) 0
#endif
#if !defined(__has_extension)
#define __has_extension(EXT) 0
#endif
#if !defined(__has_attribute)
#define __has_attribute(ATTR) 0
#endif
#ifndef __cc_printflike
#define __cc_printflike(fmtarg, firstvararg) __attribute__((format(printf, fmtarg, firstvararg)))
#endif
//Do not set this macros to 1, unless you are developing/testing for Linux under macOS
#define CORECRYPTO_SIMULATE_POSIX_ENVIRONMENT 0
//Do not set these macros to 1, unless you are developing/testing for Windows under macOS
#define CORECRYPTO_SIMULATE_WINDOWS_ENVIRONMENT 0
#define CORECRYPTO_HACK_FOR_WINDOWS_DEVELOPMENT 0
#if (defined(DEBUG) && (DEBUG)) || defined(_DEBUG) //MSVC defines _DEBUG
/* CC_DEBUG is already used in CommonCrypto */
#define CORECRYPTO_DEBUG 1
#else
#define CORECRYPTO_DEBUG 0
#endif
// Enable specific configurations only relevant in test builds
#if defined(CORECRYPTO_BUILT_FOR_TESTING) && CORECRYPTO_BUILT_FOR_TESTING
#define CC_BUILT_FOR_TESTING 1
#else
#define CC_BUILT_FOR_TESTING 0
#endif
// This macro can be used to enable prints when a condition in the macro "cc_require"
// is false. This is especially useful to confirm that negative testing fails
// at the intended location
#define CORECRYPTO_DEBUG_ENABLE_CC_REQUIRE_PRINTS 0
#ifndef CC_TXM
#if defined(TXM) && (TXM)
#define CC_TXM 1
#else
#define CC_TXM 0
#endif
#endif
#ifndef CC_SPTM
#if defined(SPTM) && (SPTM)
#define CC_SPTM 1
#else
#define CC_SPTM 0
#endif
#endif
#if defined(KERNEL) && (KERNEL)
#define CC_KERNEL 1 // KEXT, XNU repo or kernel components such as AppleKeyStore
#else
#define CC_KERNEL 0
#endif
#if defined(LINUX_SGX) && (LINUX_SGX)
#define CC_SGX 1
#else
#define CC_SGX 0
#endif
#if (defined(__linux__) && !(CC_SGX)) || CORECRYPTO_SIMULATE_POSIX_ENVIRONMENT
#define CC_LINUX 1
#else
#define CC_LINUX 0
#endif
#if defined(USE_L4) && (USE_L4)
#define CC_USE_L4 1
#else
#define CC_USE_L4 0
#endif
#if defined(RTKIT) && (RTKIT)
#define CC_RTKIT 1
#else
#define CC_RTKIT 0
#endif
#if defined(RTKITROM) && (RTKITROM)
#define CC_RTKITROM 1
#else
#define CC_RTKITROM 0
#endif
#if defined(USE_SEPROM) && (USE_SEPROM)
#define CC_USE_SEPROM 1
#else
#define CC_USE_SEPROM 0
#endif
#if (defined(ICE_FEATURES_ENABLED)) || (defined(MAVERICK) && (MAVERICK))
#define CC_BASEBAND 1
#else
#define CC_BASEBAND 0
#endif
#if defined(EFI) && (EFI)
#define CC_EFI 1
#else
#define CC_EFI 0
#endif
#if defined(IBOOT) && (IBOOT)
#define CC_IBOOT 1
#else
#define CC_IBOOT 0
#endif
// Include target conditionals if available.
#if defined(__has_include) /* portability */
#if __has_include(<TargetConditionals.h>)
#include <TargetConditionals.h>
#endif /* __has_include(<TargetConditionals.h>) */
#endif /* defined(__has_include) */
#if defined(TARGET_OS_DRIVERKIT)
#define CC_DRIVERKIT TARGET_OS_DRIVERKIT
#else
#define CC_DRIVERKIT 0
#endif
#if defined(TARGET_OS_BRIDGE)
#define CC_BRIDGE TARGET_OS_BRIDGE
#else
#define CC_BRIDGE 0
#endif
// TARGET_OS_EXCLAVECORE && TARGET_OS_EXCLAVEKIT
#if defined(TARGET_OS_EXCLAVECORE) && TARGET_OS_EXCLAVECORE
#define CC_EXCLAVE 1
#define CC_EXCLAVECORE 1
#define CC_EXCLAVEKIT 0
#elif defined(TARGET_OS_EXCLAVEKIT) && TARGET_OS_EXCLAVEKIT
#define CC_EXCLAVE 1
#define CC_EXCLAVECORE 0
#define CC_EXCLAVEKIT 1
#else
#define CC_EXCLAVE 0
#define CC_EXCLAVECORE 0
#define CC_EXCLAVEKIT 0
#endif
// ARMv6-M
#if defined(__arm__) && (defined(__ARM_ARCH_6M__) || defined(__TARGET_ARCH_6S_M) || defined (__armv6m__))
#define CC_ARM_ARCH_6M 1
#else
#define CC_ARM_ARCH_6M 0
#endif
// ARMv7
#if defined(__arm__) && (defined (__ARM_ARCH_7A__) || defined (__ARM_ARCH_7S__) || defined (__ARM_ARCH_7F__) || defined (__ARM_ARCH_7K__) || defined(__ARM_ARCH_7EM__))
#define CC_ARM_ARCH_7 1
#else
#define CC_ARM_ARCH_7 0
#endif
// DSP is only available on aarch32
#if CC_ARM_ARCH_7 && defined(__ARM_FEATURE_DSP) && __ARM_FEATURE_DSP
#define CC_ARM_ARCH_7_DSP 1
#else
#define CC_ARM_ARCH_7_DSP 0
#endif
#if defined(__ARM_NEON) && __ARM_NEON
#define CC_ARM_NEON 1
#else
#define CC_ARM_NEON 0
#endif
#if defined(__ARM_FEATURE_AES) && __ARM_FEATURE_AES
#define CC_ARM_FEATURE_AES 1
#else
#define CC_ARM_FEATURE_AES 0
#endif
#if defined(__ARM_FEATURE_SHA2) && __ARM_FEATURE_SHA2
#define CC_ARM_FEATURE_SHA2 1
#else
#define CC_ARM_FEATURE_SHA2 0
#endif
#if defined(__ARM_FEATURE_SHA512) && __ARM_FEATURE_SHA512
#define CC_ARM_FEATURE_SHA512 1
#else
#define CC_ARM_FEATURE_SHA512 0
#endif
#if defined(__ARM_FEATURE_SHA3) && __ARM_FEATURE_SHA3
#define CC_ARM_FEATURE_SHA3 1
#else
#define CC_ARM_FEATURE_SHA3 0
#endif
// Check for open source builds
// Defined by the XNU build scripts
// Applies to code embedded in XNU but NOT to the kext
#if defined(XNU_KERNEL_PRIVATE)
#define CC_XNU_KERNEL_PRIVATE 1
#else
#define CC_XNU_KERNEL_PRIVATE 0
#endif
// Handle unaligned data, if the CPU cannot. (For Gladman AES.)
#define CC_HANDLE_UNALIGNED_DATA CC_BASEBAND
// BaseBand configuration
#if CC_BASEBAND
// -- ENDIANESS
#if !defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)
#if defined(ENDIAN_LITTLE) || (defined(__arm__) && !defined(__BIG_ENDIAN))
#define __LITTLE_ENDIAN__
#elif !defined(ENDIAN_BIG) && !defined(__BIG_ENDIAN)
#error Baseband endianess not defined.
#endif
#define AESOPT_ENDIAN_NO_FILE
#endif
#if !defined(__x86_64__) && !defined(__arm64__)
// -- Architecture
#define CCN_UNIT_SIZE 4 // 32 bits
#endif
// -- Warnings
// Ignore irrelevant warnings after verification
// #186-D: pointless comparison of unsigned integer with zero
// #546-D: transfer of control bypasses initialization of
#ifdef __arm__
#pragma diag_suppress 186, 546
#endif // __arm__
#define CC_SMALL_CODE 1
#endif // CC_BASEBAND
#if CC_RTKIT || CC_RTKITROM
#define CC_SMALL_CODE 1
#endif
#ifndef CC_SMALL_CODE
#define CC_SMALL_CODE 0
#endif
#ifndef CC_DARWIN
//CC_DARWIN indicates the availability of XNU kernel functions,
//like what we have on OSX, iOS, tvOS, Watch OS
#if (CC_USE_L4 || CC_RTKIT || CC_RTKITROM || CC_USE_SEPROM || CC_EFI || CC_LINUX || defined(_WIN32) || CC_BASEBAND || CC_SGX || CC_ARM_ARCH_6M)
#define CC_DARWIN 0
#elif CC_TXM
#define CC_DARWIN 0
#elif CC_SPTM
#define CC_DARWIN 0
#else
#define CC_DARWIN 1
#endif
#endif
//arm arch64 definition for gcc
#if defined(__GNUC__) && defined(__aarch64__) && !defined(__arm64__)
#define __arm64__
#endif
#if !defined(CCN_UNIT_SIZE)
#if defined(__arm64__) || defined(__x86_64__) || defined(_WIN64)
#define CCN_UNIT_SIZE 8
#elif defined(__arm__) || defined(__i386__) || defined(_WIN32)
#define CCN_UNIT_SIZE 4
#else
#error undefined architecture
#endif
#endif /* !defined(CCN_UNIT_SIZE) */
//this allows corecrypto Windows development using xcode
#if defined(CORECRYPTO_SIMULATE_WINDOWS_ENVIRONMENT)
#if CORECRYPTO_SIMULATE_WINDOWS_ENVIRONMENT && CC_DARWIN && CORECRYPTO_DEBUG
#define CC_USE_ASM 0
#define CC_USE_HEAP_FOR_WORKSPACE 1
#if (CCN_UNIT_SIZE == 8)
#define CC_DUNIT_SUPPORTED 0
#else
#define CC_DUNIT_SUPPORTED 1
#endif
#endif
#endif
#if !defined(CC_DUNIT_SUPPORTED)
#if defined(_WIN64) && defined(_WIN32) && (CCN_UNIT_SIZE == 8)
#define CC_DUNIT_SUPPORTED 0
#else
#define CC_DUNIT_SUPPORTED 1
#endif
#endif
#if defined(_MSC_VER)
#if defined(__clang__)
#define CC_ALIGNED(x) __attribute__ ((aligned(x))) //clang compiler
#else
#define CC_ALIGNED(x) __declspec(align(x)) //MS complier
#endif
#else
#if defined(__clang__) || CCN_UNIT_SIZE==8
#define CC_ALIGNED(x) __attribute__ ((aligned(x)))
#else
#define CC_ALIGNED(x) __attribute__ ((aligned((x)>8?8:(x))))
#endif
#endif
#if !defined(CC_USE_HEAP_FOR_WORKSPACE)
#if CC_USE_SEPROM || CC_RTKITROM || CC_EFI
#define CC_USE_HEAP_FOR_WORKSPACE 0
#else
#define CC_USE_HEAP_FOR_WORKSPACE 1
#endif
#endif
// Secure memory zeroization functions
#if !defined(__APPLE__) || CC_RTKIT || CC_RTKITROM || CC_USE_SEPROM || defined(__CC_ARM) || defined(__hexagon__) || CC_EFI
#define CC_HAS_MEMSET_S 0
#else
#define CC_HAS_MEMSET_S 1
#endif
#if defined(_WIN32) && !defined(__clang__)
// Clang with Microsoft CodeGen doesn't support SecureZeroMemory.
#define CC_HAS_SECUREZEROMEMORY 1
#else
#define CC_HAS_SECUREZEROMEMORY 0
#endif
#if defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
#define CC_HAS_EXPLICIT_BZERO 1
#else
#define CC_HAS_EXPLICIT_BZERO 0
#endif
// Disable RSA keygen on iBridge.
#if !defined(CC_DISABLE_RSAKEYGEN)
#if CC_BRIDGE && CC_KERNEL
#define CC_DISABLE_RSAKEYGEN 1
#else
#define CC_DISABLE_RSAKEYGEN 0
#endif
#endif
// Enable assembler in Linux if CC_LINUX_ASM is defined
#if (CC_LINUX || CC_SGX) && defined(CC_LINUX_ASM) && CC_LINUX_ASM
#define CC_USE_ASM 1
#endif
// Use this macro to strictly disable assembly regardless of cpu/os/compiler/etc.
// Our assembly code is not gcc compatible. Clang defines the __GNUC__ macro as well.
#if !defined(CC_USE_ASM)
#if defined(_WIN32) || CC_EFI || CC_BASEBAND || CC_XNU_KERNEL_PRIVATE || (defined(__GNUC__) && !defined(__clang__)) || CC_LINUX
#define CC_USE_ASM 0
#else
#define CC_USE_ASM 1
#endif
#endif
#ifndef CC_LOG
#define CC_LOG (CC_DARWIN && !CC_KERNEL && !CC_IBOOT && !CC_DRIVERKIT && !CC_EXCLAVE)
#endif
#ifndef CC_EXTERN_MALLOC
#if CC_TXM
#define CC_EXTERN_MALLOC 1
#else
#define CC_EXTERN_MALLOC 0
#endif
#endif
#ifndef CC_MALLOC_ABORT
#if CC_SPTM
#define CC_MALLOC_ABORT 1
#else
#define CC_MALLOC_ABORT 0
#endif
#endif
#define CC_CACHE_DESCRIPTORS CC_KERNEL
//-(1) ARM V7
#if CC_ARM_ARCH_7 && defined(__clang__) && CC_USE_ASM
#define CCN_ADD_ASM 1
#define CCN_SUB_ASM 1
#define CCN_MUL_ASM 0
#define CCN_ADDMUL1_ASM 1
#define CCN_MUL1_ASM 1
#define CCN_CMP_ASM 1
#define CCN_ADD1_ASM 1
#define CCN_SUB1_ASM 1
#define CCN_N_ASM 1
#define CCN_SET_ASM 1
#define CCN_SHIFT_RIGHT_ASM 1
#if defined(__ARM_NEON__)
#define CCN_SHIFT_LEFT_ASM 1
#else
#define CCN_SHIFT_LEFT_ASM 0
#endif
#define CCN_MULMOD_224_ASM CC_ARM_ARCH_7_DSP
#define CCN_MULMOD_256_ASM CC_ARM_ARCH_7_DSP
#define CCN_MULMOD_384_ASM CC_ARM_ARCH_7_DSP
#define CCN_MULMOD_25519_ASM 0
#define CCN_MULMOD_448_ASM 0
// Clang cross-compiling for ARMv7/Linux can't handle the indirect symbol
// directives we use to reference AES tables. Skip AES assembly for now.
#if CC_LINUX && CC_BUILT_FOR_TESTING
#define CCAES_ARM_ASM 0
#else
#define CCAES_ARM_ASM 1
#endif
#define CCAES_INTEL_ASM 0
#define CCSHA1_VNG_INTEL 0
#define CCSHA2_VNG_INTEL 0
#define CCSHA3_VNG_INTEL 0
#define CCSHA3_VNG_ARM 0
#define CCSHA256_ARMV6M_ASM 0
#if defined(__ARM_NEON__) || CC_KERNEL
#define CCSHA1_VNG_ARM 1
#define CCSHA2_VNG_ARM 1
#else /* !defined(__ARM_NEON__) */
#define CCSHA1_VNG_ARM 0
#define CCSHA2_VNG_ARM 0
#endif /* !defined(__ARM_NEON__) */
//-(2) ARM 64
#elif defined(__arm64__) && defined(__clang__) && CC_USE_ASM
#define CCN_ADD_ASM 1
#define CCN_SUB_ASM 1
#define CCN_MUL_ASM 1
#define CCN_ADDMUL1_ASM 1
#define CCN_MUL1_ASM 1
#define CCN_CMP_ASM 1
#define CCN_ADD1_ASM 1
#define CCN_SUB1_ASM 0
#define CCN_N_ASM 1
#define CCN_SET_ASM 0
#define CCN_SHIFT_RIGHT_ASM CC_ARM_NEON
#define CCN_SHIFT_LEFT_ASM CC_ARM_NEON
#define CCN_MULMOD_224_ASM 1
#define CCN_MULMOD_256_ASM 1
#define CCN_MULMOD_384_ASM 1
#define CCN_MULMOD_25519_ASM 1
#define CCN_MULMOD_448_ASM 1
#define CCAES_ARM_ASM (CC_ARM_NEON && CC_ARM_FEATURE_AES)
#define CCAES_INTEL_ASM 0
#define CCSHA1_VNG_INTEL 0
#define CCSHA2_VNG_INTEL 0
#define CCSHA3_VNG_INTEL 0
#define CCSHA1_VNG_ARM 1
#define CCSHA2_VNG_ARM (CC_ARM_NEON && CC_ARM_FEATURE_SHA2)
#define CCSHA256_ARMV6M_ASM 0
#if CC_USE_L4 || CC_KERNEL
#define CCSHA3_VNG_ARM 0
#else
#define CCSHA3_VNG_ARM 1
#endif
//-(3) Intel 32/64
#elif (defined(__x86_64__) || defined(__i386__)) && defined(__clang__) && CC_USE_ASM
/* These assembly routines only work for a single CCN_UNIT_SIZE. */
#if (defined(__x86_64__) && CCN_UNIT_SIZE == 8) || (defined(__i386__) && CCN_UNIT_SIZE == 4)
#define CCN_ADD_ASM 1
#define CCN_SUB_ASM 1
#define CCN_MUL_ASM 1
#else
#define CCN_ADD_ASM 0
#define CCN_SUB_ASM 0
#define CCN_MUL_ASM 0
#endif
#if (defined(__x86_64__) && CCN_UNIT_SIZE == 8)
#define CCN_CMP_ASM 1
#define CCN_N_ASM 1
#define CCN_SHIFT_RIGHT_ASM 1
#define CCN_SHIFT_LEFT_ASM 1
#else
#define CCN_CMP_ASM 0
#define CCN_N_ASM 0
#define CCN_SHIFT_RIGHT_ASM 0
#define CCN_SHIFT_LEFT_ASM 0
#endif
#define CCN_MULMOD_384_ASM 0
#define CCN_MULMOD_448_ASM 0
#if defined(__x86_64__) && CCN_UNIT_SIZE == 8 && !CC_SGX
#define CCN_MULMOD_224_ASM 1
#define CCN_MULMOD_256_ASM 1
#define CCN_MULMOD_25519_ASM 1
#define CCN_ADDMUL1_ASM 1
#define CCN_MUL1_ASM 1
#else
#define CCN_MULMOD_224_ASM 0
#define CCN_MULMOD_256_ASM 0
#define CCN_MULMOD_25519_ASM 0
#define CCN_ADDMUL1_ASM 0
#define CCN_MUL1_ASM 0
#endif
#define CCN_ADD1_ASM 0
#define CCN_SUB1_ASM 0
#define CCN_SET_ASM 0
#define CCAES_ARM_ASM 0
#define CCAES_INTEL_ASM 1
#define CCSHA1_VNG_INTEL 1
#define CCSHA2_VNG_INTEL 1
#define CCSHA3_VNG_INTEL 1
#define CCSHA1_VNG_ARM 0
#define CCSHA2_VNG_ARM 0
#define CCSHA3_VNG_ARM 0
#define CCSHA256_ARMV6M_ASM 0
//-(4) ARMv6-M
#elif CC_ARM_ARCH_6M
#define CCN_ADD_ASM 0
#define CCN_SUB_ASM 0
#define CCN_MUL_ASM 0
#define CCN_ADDMUL1_ASM 0
#define CCN_MUL1_ASM 0
#define CCN_CMP_ASM 0
#define CCN_ADD1_ASM 0
#define CCN_SUB1_ASM 0
#define CCN_N_ASM 0
#define CCN_SET_ASM 0
#define CCN_SHIFT_RIGHT_ASM 0
#define CCN_SHIFT_LEFT_ASM 0
#define CCN_MULMOD_224_ASM 0
#define CCN_MULMOD_256_ASM 0
#define CCN_MULMOD_384_ASM 0
#define CCN_MULMOD_25519_ASM 0
#define CCN_MULMOD_448_ASM 0
#define CCAES_ARM_ASM 0
#define CCAES_INTEL_ASM 0
#define CCSHA1_VNG_INTEL 0
#define CCSHA2_VNG_INTEL 0
#define CCSHA3_VNG_INTEL 0
#define CCSHA1_VNG_ARM 0
#define CCSHA2_VNG_ARM 0
#define CCSHA3_VNG_ARM 0
#define CCSHA256_ARMV6M_ASM 1
//-(5) disable assembly
#else
#define CCN_ADD_ASM 0
#define CCN_SUB_ASM 0
#define CCN_MUL_ASM 0
#define CCN_ADDMUL1_ASM 0
#define CCN_MUL1_ASM 0
#define CCN_CMP_ASM 0
#define CCN_ADD1_ASM 0
#define CCN_SUB1_ASM 0
#define CCN_N_ASM 0
#define CCN_SET_ASM 0
#define CCN_SHIFT_RIGHT_ASM 0
#define CCN_SHIFT_LEFT_ASM 0
#define CCN_MULMOD_224_ASM 0
#define CCN_MULMOD_256_ASM 0
#define CCN_MULMOD_384_ASM 0
#define CCN_MULMOD_25519_ASM 0
#define CCN_MULMOD_448_ASM 0
#define CCAES_ARM_ASM 0
#define CCAES_INTEL_ASM 0
#define CCSHA1_VNG_INTEL 0
#define CCSHA2_VNG_INTEL 0
#define CCSHA3_VNG_INTEL 0
#define CCSHA1_VNG_ARM 0
#define CCSHA2_VNG_ARM 0
#define CCSHA3_VNG_ARM 0
#define CCSHA256_ARMV6M_ASM 0
#endif
#define CC_INLINE static inline
#define CC_NONNULL4 CC_NONNULL((4))
#ifdef __GNUC__
#define CC_NORETURN __attribute__((__noreturn__))
#define CC_NOTHROW __attribute__((__nothrow__))
#define CC_NONNULL(N) __attribute__((__nonnull__ N))
#define CC_NONNULL_ALL __attribute__((__nonnull__))
#define CC_SENTINEL __attribute__((__sentinel__))
// Only apply the `CC_CONST` attribute to functions with no side-effects where the output is a strict function of pass by value input vars with no exterior side-effects.
// Specifically, do not apply CC_CONST if the function has any arguments that are pointers (directly, or indirectly)
#define CC_CONST __attribute__((__const__))
#define CC_PURE __attribute__((__pure__))
#define CC_NODISCARD __attribute__((warn_unused_result))
#define CC_WARN_RESULT __attribute__((__warn_unused_result__))
#define CC_MALLOC_CLEAR __attribute__((__malloc__))
#define CC_UNUSED __attribute__((unused))
#define CC_WEAK __attribute__((weak))
#elif defined(__KEIL__)
#define CC_NORETURN __attribute__((noreturn))
#define CC_NOTHROW __attribute__((nothrow))
#define CC_NONNULL(N) __attribute__((nonnull N))
#define CC_NONNULL_ALL __attribute__((nonnull))
#define CC_SENTINEL __attribute__((sentinel))
#define CC_CONST __attribute__((const))
#define CC_PURE __attribute__((pure))
#define CC_NODISCARD __attribute__((warn_unused_result))
#define CC_WARN_RESULT __attribute__((warn_unused_result))
#define CC_MALLOC_CLEAR __attribute__((malloc))
#define CC_UNUSED __attribute__((unused))
#define CC_WEAK __attribute__((weak))
#else /* !__GNUC__ */
/*! @parseOnly */
#define CC_UNUSED
/*! @parseOnly */
#define CC_NONNULL(N)
/*! @parseOnly */
#define CC_NORETURN
/*! @parseOnly */
#define CC_NOTHROW
/*! @parseOnly */
#define CC_NONNULL_ALL
/*! @parseOnly */
#define CC_SENTINEL
/*! @parseOnly */
#define CC_CONST
/*! @parseOnly */
#define CC_PURE
/*! @parseOnly */
#define CC_NODISCARD
/*! @parseOnly */
#define CC_WARN_RESULT
/*! @parseOnly */
#define CC_MALLOC_CLEAR
/*! @parseOnly */
#define CC_WEAK
#endif /* !__GNUC__ */
// Use CC_WEAK_IF_SMALL_CODE to mark symbols as weak when compiling with
// CC_SMALL_CODE=1. This allows replacing faster but bigger code with smaller
// versions at link time.
#if CC_SMALL_CODE && !CC_BUILT_FOR_TESTING
#define CC_WEAK_IF_SMALL_CODE CC_WEAK
#else
#define CC_WEAK_IF_SMALL_CODE
#endif
// Bridge differences between MachO and ELF compiler/assemblers. */
#if CC_LINUX || CC_SGX
#define CC_ASM_SECTION_CONST .rodata
#define CC_ASM_PRIVATE_EXTERN .hidden
#define CC_ASM_SUBSECTIONS_VIA_SYMBOLS
#if CC_LINUX
// We need to be sure that assembler can access relocated C
// symbols. Sad but this is the quickest way to do that, at least with
// our current linux compiler (clang-3.4).
#define CC_C_LABEL(_sym) _sym@PLT
#else /* CC_SGX */
#define CC_C_LABEL(_sym) _sym
#endif
#define _IMM(x) $(x)
#else /* !CC_LINUX && !CC_SGX */
#define CC_ASM_SECTION_CONST .const
#define CC_ASM_PRIVATE_EXTERN .private_extern
#define CC_ASM_SUBSECTIONS_VIA_SYMBOLS .subsections_via_symbols
#define CC_C_LABEL(_sym) _##_sym
#define _IMM(x) $$(x)
#endif /* !CC_LINUX && !CC_SGX */
// Enable FIPSPOST function tracing only when supported. */
#ifdef CORECRYPTO_POST_TRACE
#define CC_FIPSPOST_TRACE 1
#else
#define CC_FIPSPOST_TRACE 0
#endif
#ifndef CC_INTERNAL_SDK
#if __has_include(<System/i386/cpu_capabilities.h>)
#define CC_INTERNAL_SDK 1
#elif __has_include(<System/arm/cpu_capabilities.h>)
#define CC_INTERNAL_SDK 1
#else
#define CC_INTERNAL_SDK 0
#endif
#endif
#if __has_feature(address_sanitizer)
#define CC_ASAN 1
#else
#define CC_ASAN 0
#endif
#ifdef CORECRYPTO_COVERAGE
#define CC_COVERAGE 1
#else
#define CC_COVERAGE 0
#endif
// Currently thread sanitizer is only supported in local builds.
// Please edit your "corecrypto_test" scheme to build with thread
// sanitizer and then remove *all* variants of corecrypto_static
// besides "normal"
#if __has_feature(thread_sanitizer)
#define CC_TSAN 1
#else
#define CC_TSAN 0
#endif // __has_feature(thread_sanitizer)
#if __has_feature(bounds_attributes)
#define CC_PTRCHECK 1
#define CC_PTRCHECK_CAPABLE_HEADER() _Pragma("clang abi_ptr_attr set(single)")
#define cc_counted_by(x) __attribute__((counted_by(x)))
#define cc_sized_by(x) __attribute__((sized_by(x)))
#define cc_bidi_indexable __attribute__((bidi_indexable))
#define cc_indexable __attribute__((indexable))
#define cc_single __attribute__((single))
#define cc_unsafe_indexable __attribute__((unsafe_indexable))
#define cc_unsafe_forge_bidi_indexable(P, S) __builtin_unsafe_forge_bidi_indexable(P, S)
#define cc_unsafe_forge_single(P) __builtin_unsafe_forge_single(P)
#define cc_cstring cc_unsafe_indexable
#define CC_WIDE_NULL ((void *cc_bidi_indexable)NULL)
#define cc_ended_by(x) __attribute__((ended_by(x)))
#define cc_ptrcheck_unavailable_r(r) __ptrcheck_unavailable_r(r)
#else
#define CC_PTRCHECK 0
#define CC_PTRCHECK_CAPABLE_HEADER()
#define cc_counted_by(x)
#define cc_sized_by(x)
#define cc_bidi_indexable
#define cc_indexable
#define cc_single
#define cc_unsafe_indexable
#define cc_unsafe_forge_bidi_indexable(P, S) (P)
#define cc_unsafe_forge_single(P) (P)
#define cc_cstring
#define CC_WIDE_NULL NULL
#define cc_ended_by(x)
#define cc_ptrcheck_unavailable_r(r)
#endif // __has_feature(bounds_attributes)
// Define endianess for GCC, if needed and applicable.
#if defined(__GNUC__) && !defined(__LITTLE_ENDIAN__)
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define __LITTLE_ENDIAN__ 1
#endif
#endif
#if defined(ENABLE_CRYPTOKIT_PRIVATE_DEFINITIONS) && ENABLE_CRYPTOKIT_PRIVATE_DEFINITIONS
#define CC_PRIVATE_CRYPTOKIT 1
#else
#define CC_PRIVATE_CRYPTOKIT 0
#endif
#if defined(__clang__)
#define CC_WORKSPACE_OVERRIDE_PRAGMA(x) _Pragma(#x)
#define CC_WORKSPACE_OVERRIDE(f, o) CC_WORKSPACE_OVERRIDE_PRAGMA(workspace-override f o)
#else
#define CC_WORKSPACE_OVERRIDE(f, o)
#endif
#ifndef CC_DIT_MAYBE_SUPPORTED
#if defined(__arm64__) && !CC_USE_L4 && !CC_USE_SEPROM && !CC_IBOOT
#define CC_DIT_MAYBE_SUPPORTED 1
#else
#define CC_DIT_MAYBE_SUPPORTED 0
#endif
#endif
#endif /* _CORECRYPTO_CC_CONFIG_H_ */

View file

@ -0,0 +1,202 @@
/* Copyright (c) (2017-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CC_ERROR_H_
#define _CORECRYPTO_CC_ERROR_H_
enum {
CCERR_OK = 0,
/* the default error code */
CCERR_INTERNAL = -1,
CCERR_INTEGRITY = -2,
CCERR_DEVICE = -3,
CCERR_INTERRUPTS = -4,
CCERR_CRYPTO_CONFIG = -5,
CCERR_PERMS = -6,
CCERR_PARAMETER = -7,
CCERR_MEMORY = -8,
CCERR_FILEDESC = -9,
CCERR_OUT_OF_ENTROPY = -10,
CCERR_ATFORK = -11,
CCERR_OVERFLOW = -12,
CCERR_MEMORY_ALLOC_FAIL = -13,
CCEC_GENERATE_KEY_DEFAULT_ERR = -14,
CCEC_GENERATE_KEY_TOO_MANY_TRIES = -15,
CCEC_GENERATE_KEY_MULT_FAIL = -16,
CCEC_GENERATE_KEY_AFF_FAIL = -17,
CCEC_GENERATE_KEY_CONSISTENCY = -18,
CCEC_GENERATE_NOT_ON_CURVE = -19,
CCEC_GENERATE_NOT_ENOUGH_ENTROPY = -20,
CCEC_GENERATE_NOT_SUPPORTED = -21,
CCEC_GENERATE_INVALID_INPUT = -22,
// Program error: buffer too small or encrypted message is too small
CCRSA_INVALID_INPUT = -23,
// Invalid crypto configuration: Hash length versus RSA key size
CCRSA_INVALID_CONFIG = -24,
CCRSA_ENCODING_ERROR = -25,
CCRSA_DECODING_ERROR = -26,
// The data is invalid (we won't say more for security)
CCRSA_PRIVATE_OP_ERROR = -27,
CCRSA_KEY_ERROR = -28,
// Key generation specific
CCRSA_KEYGEN_PRIME_NOT_FOUND = -29,
CCRSA_KEYGEN_PRIME_NEED_NEW_SEED = -30,
CCRSA_KEYGEN_PRIME_TOO_MANY_ITERATIONS = -31,
CCRSA_KEYGEN_PRIME_SEED_GENERATION_ERROR = -32,
CCRSA_KEYGEN_MODULUS_CRT_INV_ERROR = -33,
CCRSA_KEYGEN_NEXT_PRIME_ERROR = -34,
CCRSA_KEYGEN_SEED_X_ERROR = -35,
CCRSA_KEYGEN_SEED_r_ERROR = -36,
CCRSA_KEYGEN_KEYGEN_CONSISTENCY_FAIL = -37,
CCRSA_KEYGEN_R1R2_SIZE_ERROR = -38,
CCRSA_KEYGEN_PQ_DELTA_ERROR = -39,
CCRSA_FIPS_KEYGEN_DISABLED = -40,
CCZP_INV_ERROR = -41,
CCZP_INV_NO_INVERSE = -42,
CCZP_INV_INVALID_INPUT = -43,
CCZ_INVALID_INPUT_ERROR = -44,
CCZ_INVALID_RADIX_ERROR = -45,
CCDH_ERROR_DEFAULT = -46,
CCDH_GENERATE_KEY_TOO_MANY_TRIES = -47,
CCDH_NOT_SUPPORTED_CONFIGURATION = -48,
CCDH_SAFETY_CHECK = -49,
CCDH_PUBLIC_KEY_MISSING = -50,
CCDH_INVALID_DOMAIN_PARAMETER = -51,
CCDH_INVALID_INPUT = -52,
CCDH_DOMAIN_PARAMETER_MISMATCH = -53,
CCDH_GENERATE_KEY_CONSISTENCY = -54,
CCSRP_ERROR_DEFAULT = -55,
CCSRP_GENERATE_KEY_TOO_MANY_TRIES = -56,
CCSRP_NOT_SUPPORTED_CONFIGURATION = -57,
CCSRP_SAFETY_CHECK = -58,
CCSRP_PUBLIC_KEY_MISSING = -59,
CCSRP_INVALID_DOMAIN_PARAMETER = -60,
CCDRBG_STATUS_ERROR = -61,
CCDRBG_STATUS_NEED_RESEED = -62,
CCDRBG_STATUS_PARAM_ERROR = -63,
// If this value is returned, the caller must abort or panic the process for
// security reasons. For example in the case of catastrophic error in
// http://csrc.nist.gov/publications/drafts/800-90/sp800_90a_r1_draft.pdf
// ccdrbg calls abort() or panic(), if they are available in the system.
CCDRBG_STATUS_ABORT = -64,
CCKPRNG_NEED_ENTROPY = -65,
CCKPRNG_ABORT = -66,
CCMODE_INVALID_INPUT = -67,
CCMODE_INVALID_CALL_SEQUENCE = -68,
CCMODE_INTEGRITY_FAILURE = -69,
CCMODE_NOT_SUPPORTED = -70,
CCMODE_INTERNAL_ERROR = -71,
// Configuration or unexpected issue
CCPOST_GENERIC_FAILURE = -72,
CCPOST_LIBRARY_ERROR = -73,
CCPOST_INTEGRITY_ERROR = -74,
// Output of the algo is not as expected
CCPOST_KAT_FAILURE = -75,
CCKPRNG_SEEDFILE_OPEN = -76,
CCKPRNG_SEEDFILE_READ = -78,
CCKPRNG_SEEDFILE_WRITE = -79,
CCKPRNG_SEEDFILE_CHMOD = -80,
CCKPRNG_SEEDFILE_CHOWN = -81,
CCKPRNG_RANDOMDEV_OPEN = -82,
CCKPRNG_RANDOMDEV_WRITE = -83,
CCKPRNG_GETENTROPY = -84,
CCSAE_HUNTPECK_EXCEEDED_MAX_TRIALS = -85,
CCERR_CALL_SEQUENCE = -86,
CCVRF_POINT_DECODE_FAILURE = -87,
CCVRF_POINT_INVALID_PUBLIC_KEY = -88,
CCVRF_VERIFY_FAILURE = -89,
// Error codes for Authenticated Encryption Modes
CCMODE_TAG_LENGTH_REQUEST_TOO_LONG = -100,
CCMODE_TAG_LENGTH_TOO_SHORT = -101,
CCMODE_NONCE_EMPTY = -102,
CCMODE_AD_EMPTY = -103,
CCMODE_DECRYPTION_OR_VERIFICATION_ERR=-104,
CCMODE_BUFFER_OUT_IN_OVERLAP = -105,
// Error codes for Secret Sharing
CCSS_ELEMENT_TOO_LARGE_FOR_FIELD = -120,
CCSS_NOT_ENOUGH_SHARES = -121,
CCSS_TOO_MANY_SHARES = -122,
CCSS_IMPROPER_DEGREE = -123,
CCSS_TWO_SHARES_FOR_SAME_X = -124,
CCSS_THRESHOLD_NOT_LARGE_ENOUGH = -125,
CCSS_SHARE_BAG_FULL = -126,
CCSS_SHARE_ALREADY_PRESENT_IN_SHARE_BAG = -127,
CCSS_THRESHOLD_LARGER_OR_EQUAL_TO_FIELD = -128,
CCSS_TOO_MANY_SHARES_REQUESTED = -129,
CCSS_FIELD_MISMATCH = -130,
CCSS_INDEX_OUT_OF_RANGE = -131,
CCSAE_NOT_ENOUGH_COMMIT_PARTIAL_CALLS = -132,
CCSAE_GENERATE_COMMIT_CALL_AGAIN = -133,
CCERR_VALID_SIGNATURE = CCERR_OK,
CCERR_INVALID_SIGNATURE = -146,
CCERR_IOSERVICE_GETMATCHING = -147,
CCERR_IOSERVICE_OPEN = -148,
CCERR_IOCONNECT_CALL = -149,
CCEC_KEY_CANNOT_BE_UNIT = -160,
CCEC_COMPRESSED_POINT_ENCODING_ERROR = -161,
CCERR_RNG_NOT_SEEDED = -162,
CCERR_BUFFER_TOO_SMALL = -163,
CCERR_XTS_KEYS_EQUAL = -164,
CCERR_RETRY = -165,
CCDH_GP_P_NOTPRIME = -166,
CCDH_GP_Q_NOTPRIME = -167,
CCDH_GP_NONSAFE_PRIME = -168,
// -169, // deprecated
CCEC_POINT_CANNOT_BE_UNIT = CCEC_KEY_CANNOT_BE_UNIT,
CCEC_UNCOMPRESSED_POINT_ENCODING_ERROR = -170,
CCEC_HYBRID_POINT_ENCODING_ERROR = -171,
CCEC_COMPACT_POINT_ENCODING_ERROR = -172,
CCERR_NOT_SUPPORTED = -173,
// Always add error codes above this line, and always keep
// their value greater than the value of CCERR_MIN.
CCERR_MIN = -255,
};
#define CCDRBG_STATUS_OK CCERR_OK
#define CCKPRNG_OK CCERR_OK
#endif /* _CORECRYPTO_CC_ERROR_H_ */

View file

@ -0,0 +1,30 @@
/* Copyright (c) (2019-2023) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CC_FAULT_CANARY_H_
#define _CORECRYPTO_CC_FAULT_CANARY_H_
#include "cc.h"
CC_PTRCHECK_CAPABLE_HEADER()
#define CC_FAULT_CANARY_SIZE 16
typedef uint8_t cc_fault_canary_t[CC_FAULT_CANARY_SIZE];
extern const cc_fault_canary_t CCEC_FAULT_CANARY;
extern const cc_fault_canary_t CCRSA_PKCS1_FAULT_CANARY;
extern const cc_fault_canary_t CCRSA_PSS_FAULT_CANARY;
#define CC_FAULT_CANARY_MEMCPY(_dst_, _src_) cc_memcpy(_dst_, _src_, CC_FAULT_CANARY_SIZE)
#define CC_FAULT_CANARY_CLEAR(_name_) cc_memset(_name_, 0x00, CC_FAULT_CANARY_SIZE)
#define CC_FAULT_CANARY_EQUAL(_a_, _b_) (cc_cmp_safe(CC_FAULT_CANARY_SIZE, _a_, _b_) == 0)
#endif // _CORECRYPTO_CC_FAULT_CANARY_H_

View file

@ -0,0 +1,67 @@
/* Copyright (c) (2021) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CC_IMPL_H_
#define _CORECRYPTO_CC_IMPL_H_
#define CC_IMPL_LIST \
CC_IMPL_ITEM(UNKNOWN, 0) \
\
CC_IMPL_ITEM(SHA256_LTC, 1) \
CC_IMPL_ITEM(SHA256_VNG_ARM, 2) \
CC_IMPL_ITEM(SHA256_VNG_ARM64_NEON, 3) \
CC_IMPL_ITEM(SHA256_VNG_INTEL_SUPPLEMENTAL_SSE3, 4) \
CC_IMPL_ITEM(SHA256_VNG_INTEL_AVX1, 5) \
CC_IMPL_ITEM(SHA256_VNG_INTEL_AVX2, 6) \
\
CC_IMPL_ITEM(AES_ECB_LTC, 11) \
CC_IMPL_ITEM(AES_ECB_ARM, 12) \
CC_IMPL_ITEM(AES_ECB_INTEL_OPT, 13) \
CC_IMPL_ITEM(AES_ECB_INTEL_AESNI, 14) \
CC_IMPL_ITEM(AES_ECB_SKG, 15) \
CC_IMPL_ITEM(AES_ECB_TRNG, 16) \
\
CC_IMPL_ITEM(AES_XTS_GENERIC, 21) \
CC_IMPL_ITEM(AES_XTS_ARM, 22) \
CC_IMPL_ITEM(AES_XTS_INTEL_OPT, 23) \
CC_IMPL_ITEM(AES_XTS_INTEL_AESNI, 24) \
\
CC_IMPL_ITEM(SHA1_LTC, 31) \
CC_IMPL_ITEM(SHA1_VNG_ARM, 32) \
CC_IMPL_ITEM(SHA1_VNG_INTEL_SUPPLEMENTAL_SSE3, 33) \
CC_IMPL_ITEM(SHA1_VNG_INTEL_AVX1, 34) \
CC_IMPL_ITEM(SHA1_VNG_INTEL_AVX2, 35) \
\
CC_IMPL_ITEM(SHA384_LTC, 41) \
CC_IMPL_ITEM(SHA384_VNG_ARM, 42) \
CC_IMPL_ITEM(SHA384_VNG_INTEL_SUPPLEMENTAL_SSE3, 43) \
CC_IMPL_ITEM(SHA384_VNG_INTEL_AVX1, 44) \
CC_IMPL_ITEM(SHA384_VNG_INTEL_AVX2, 45) \
\
CC_IMPL_ITEM(SHA512_LTC, 51) \
CC_IMPL_ITEM(SHA512_VNG_ARM, 52) \
CC_IMPL_ITEM(SHA512_VNG_INTEL_SUPPLEMENTAL_SSE3, 53) \
CC_IMPL_ITEM(SHA512_VNG_INTEL_AVX1, 54) \
CC_IMPL_ITEM(SHA512_VNG_INTEL_AVX2, 55)
#define CC_IMPL_ITEM(k, v) \
CC_IMPL_##k = v,
typedef enum cc_impl {
CC_IMPL_LIST
} cc_impl_t;
#undef CC_IMPL_ITEM
const char *cc_impl_name(cc_impl_t impl);
#endif /* _CORECRYPTO_CC_IMPL_H_ */

View file

@ -0,0 +1,183 @@
/* Copyright (c) (2021-2023) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CC_LOCK_H_
#define _CORECRYPTO_CC_LOCK_H_
#include <corecrypto/cc_priv.h>
typedef struct cc_lock_ctx cc_lock_ctx_t;
int cc_lock_init(cc_lock_ctx_t *ctx, const char *group_name);
#if defined(_WIN32)
#include <windows.h>
#endif
//==============================================================================
//
// corecrypto support for multithreaded environments
//
// This part of corecrypto is OS dependent and it serves two purposes
// a) It allows multiple threads to use ccrng()
// b) If the process is forked, it reseeds the ccrng, so that parent and child
// state differs and generate different random numbers
//==============================================================================
#if CC_USE_L4 || CC_USE_SEPROM || CC_RTKIT || CC_RTKITROM
#define CC_LOCK_IMPL_NULL 1
#define CC_LOCK_IMPL_POSIX 0
#define CC_LOCK_IMPL_USER 0
#define CC_LOCK_IMPL_WIN 0
#define CC_LOCK_IMPL_KERNEL 0
#define CC_LOCK_IMPL_SGX 0
#elif CC_LINUX && CC_KERNEL && CC_DARWIN && CORECRYPTO_SIMULATE_POSIX_ENVIRONMENT
// this is only to allow linux development on macOS. It is not useful in practice.
#define CC_LOCK_IMPL_NULL 0
#define CC_LOCK_IMPL_POSIX 0
#define CC_LOCK_IMPL_USER 0
#define CC_LOCK_IMPL_WIN 0
#define CC_LOCK_IMPL_KERNEL 1
#define CC_LOCK_IMPL_SGX 0
#elif CC_DARWIN && !CC_KERNEL && !CC_EFI && CC_INTERNAL_SDK
// For Apple OSs (macOS, iOS, watchOS, tvOS), except kernel, L4 and EFI
#define CC_LOCK_IMPL_NULL 0
#define CC_LOCK_IMPL_POSIX 0
#define CC_LOCK_IMPL_USER 1
#define CC_LOCK_IMPL_WIN 0
#define CC_LOCK_IMPL_KERNEL 0
#define CC_LOCK_IMPL_SGX 0
#elif CC_DARWIN && CC_KERNEL // For the Apple Kernel
#define CC_LOCK_IMPL_NULL 0
#define CC_LOCK_IMPL_POSIX 0
#define CC_LOCK_IMPL_USER 0
#define CC_LOCK_IMPL_WIN 0
#define CC_LOCK_IMPL_KERNEL 1
#define CC_LOCK_IMPL_SGX 0
#elif defined(_WIN32) // for Windows
#define CC_LOCK_IMPL_NULL 0
#define CC_LOCK_IMPL_POSIX 0
#define CC_LOCK_IMPL_USER 0
#define CC_LOCK_IMPL_WIN 1
#define CC_LOCK_IMPL_KERNEL 0
#define CC_LOCK_IMPL_SGX 0
#elif CC_SGX // for SGX Enclave
#define CC_LOCK_IMPL_NULL 0
#define CC_LOCK_IMPL_POSIX 0
#define CC_LOCK_IMPL_USER 0
#define CC_LOCK_IMPL_WIN 0
#define CC_LOCK_IMPL_KERNEL 0
#define CC_LOCK_IMPL_SGX 1
#elif CC_LINUX || !CC_INTERNAL_SDK // for systems that support pthread, such as Linux
#define CC_LOCK_IMPL_NULL 0
#define CC_LOCK_IMPL_POSIX 1
#define CC_LOCK_IMPL_USER 0
#define CC_LOCK_IMPL_WIN 0
#define CC_LOCK_IMPL_KERNEL 0
#define CC_LOCK_IMPL_SGX 0
#else
#error No multithread environment defined for cc_lock.
#endif
#if CC_LOCK_IMPL_NULL
#define CC_LOCK_LOCK(lock_ctx) cc_try_abort("CC_LOCK_LOCK not implemented")
#define CC_LOCK_TRYLOCK(lock_ctx) cc_try_abort("CC_LOCK_TRYLOCK not implemented")
#define CC_LOCK_UNLOCK(lock_ctx) cc_try_abort("CC_LOCK_UNLOCK not implemented")
#define CC_LOCK_ASSERT(lock_ctx) cc_try_abort("CC_LOCK_ASSERT not implemented")
struct cc_lock_ctx {
};
//------------------------------------------------------------------------------
// os/lock library, Apple userland
//------------------------------------------------------------------------------
#elif CC_LOCK_IMPL_USER
#include <pthread.h>
#include <os/lock.h>
#define CC_LOCK_LOCK(lock_ctx) os_unfair_lock_lock(&(lock_ctx)->lock)
#define CC_LOCK_TRYLOCK(lock_ctx) os_unfair_lock_trylock(&(lock_ctx)->lock)
#define CC_LOCK_UNLOCK(lock_ctx) os_unfair_lock_unlock(&(lock_ctx)->lock)
#define CC_LOCK_ASSERT(lock_ctx) os_unfair_lock_assert_owner(&(lock_ctx)->lock)
struct cc_lock_ctx {
os_unfair_lock lock;
};
//------------------------------------------------------------------------------
// POSIX library, Linux
//------------------------------------------------------------------------------
#elif CC_LOCK_IMPL_POSIX
#include <pthread.h>
#define CC_LOCK_LOCK(lock_ctx) (pthread_mutex_lock(&(lock_ctx)->mutex) == 0)
#define CC_LOCK_TRYLOCK(lock_ctx) (pthread_mutex_trylock(&(lock_ctx)->mutex) == 0)
#define CC_LOCK_UNLOCK(lock_ctx) (pthread_mutex_unlock(&(lock_ctx)->mutex) == 0)
#define CC_LOCK_ASSERT(lock_ctx) do { } while (0)
struct cc_lock_ctx {
pthread_mutex_t mutex;
};
//------------------------------------------------------------------------------
// Kext, XNU
//------------------------------------------------------------------------------
#elif CC_LOCK_IMPL_KERNEL
#include <kern/locks.h>
#define CC_LOCK_LOCK(lock_ctx) lck_mtx_lock((lock_ctx)->mutex)
#define CC_LOCK_TRYLOCK(lock_ctx) lck_mtx_try_lock((lock_ctx)->mutex)
#define CC_LOCK_UNLOCK(lock_ctx) lck_mtx_unlock((lock_ctx)->mutex)
#define CC_LOCK_ASSERT(lock_ctx) lck_mtx_assert((lock_ctx)->mutex, LCK_MTX_ASSERT_OWNED);
struct cc_lock_ctx {
lck_mtx_t *mutex;
lck_grp_t *group;
};
//------------------------------------------------------------------------------
// Windows
//------------------------------------------------------------------------------
#elif CC_LOCK_IMPL_WIN
#define CC_LOCK_LOCK(lock_ctx) \
if (WaitForSingleObject((lock_ctx)->hMutex, INFINITE) != WAIT_OBJECT_0) \
return CCERR_INTERNAL;
#define CC_LOCK_UNLOCK(lock_ctx) ReleaseMutex((lock_ctx)->hMutex)
#define CC_LOCK_ASSERT(lock_ctx) do { } while (0)
struct cc_lock_ctx {
HANDLE hMutex;
};
//------------------------------------------------------------------------------
// SGX
//------------------------------------------------------------------------------
#elif CC_LOCK_IMPL_SGX
// Avoid an OCALL in the middle of RNG routines: use spinlocks instead of mutexes.
#include <pthread.h>
#define CC_LOCK_LOCK(lock_ctx) pthread_spin_lock(&(lock_ctx)->lock)
#define CC_LOCK_UNLOCK(lock_ctx) pthread_spin_unlock(&(lock_ctx)->lock)
#define CC_LOCK_ASSERT(lock_ctx) do { } while (0)
struct cc_lock_ctx {
pthread_spinlock_t lock;
};
//------------------------------------------------------------------------------
// default
//------------------------------------------------------------------------------
#else
#error "cc_lock is not implemented."
#endif /* CC_LOCK_IMPL_USER */
#endif /* _CORECRYPTO_CC_LOCK_H_ */

View file

@ -0,0 +1,150 @@
/* Copyright (c) (2012,2015,2016,2017,2019) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CC_MACROS_H_
#define _CORECRYPTO_CC_MACROS_H_
#include <corecrypto/cc_config.h>
#ifndef __CC_DEBUG_ASSERT_COMPONENT_NAME_STRING
#define __CC_DEBUG_ASSERT_COMPONENT_NAME_STRING ""
#endif
#ifndef __CC_DEBUG_ASSERT_PRODUCTION_CODE
#define __CC_DEBUG_ASSERT_PRODUCTION_CODE !CORECRYPTO_DEBUG
#endif
#if CORECRYPTO_DEBUG_ENABLE_CC_REQUIRE_PRINTS
#if !CC_KERNEL
#include <string.h> // for strstr
#endif // !CC_KERNEL
CC_UNUSED static char *cc_strstr(const char *file) {
#if CC_KERNEL
(void) file;
#else
const char cc_char []="corecrypto";
char *p=strstr(file, cc_char);
if (p) return (p+strlen(cc_char)+1);
#endif
return NULL;
}
#define __CC_DEBUG_REQUIRE_MESSAGE(name, assertion, label, message, file, line, value) \
{char *___t = cc_strstr(file); cc_printf( "require: %s, %s%s:%d\n", assertion, (message!=0) ? message : "", ___t==NULL?file:___t, line);}
#endif // CORECRYPTO_DEBUG_ENABLE_CC_REQUIRE_PRINTS
#ifndef cc_require
#if (__CC_DEBUG_ASSERT_PRODUCTION_CODE) || (!CORECRYPTO_DEBUG_ENABLE_CC_REQUIRE_PRINTS)
#if defined(_WIN32) && defined (__clang__)
#define cc_require(assertion, exceptionLabel) \
do { \
if (!(assertion) ) { \
goto exceptionLabel; \
} \
} while ( 0 )
#else
#define cc_require(assertion, exceptionLabel) \
do { \
if ( __builtin_expect(!(assertion), 0) ) { \
goto exceptionLabel; \
} \
} while ( 0 )
#endif
#else
#define cc_require(assertion, exceptionLabel) \
do { \
if ( __builtin_expect(!(assertion), 0) ) { \
__CC_DEBUG_REQUIRE_MESSAGE(__CC_DEBUG_ASSERT_COMPONENT_NAME_STRING, \
#assertion, #exceptionLabel, 0, __FILE__, __LINE__, 0); \
goto exceptionLabel; \
} \
} while ( 0 )
#endif
#endif
#ifndef cc_require_action
#if __CC_DEBUG_ASSERT_PRODUCTION_CODE || (!CORECRYPTO_DEBUG_ENABLE_CC_REQUIRE_PRINTS)
#if defined(_WIN32) && defined(__clang__)
#define cc_require_action(assertion, exceptionLabel, action) \
do \
{ \
if (!(assertion)) \
{ \
{ \
action; \
} \
goto exceptionLabel; \
} \
} while ( 0 )
#else
#define cc_require_action(assertion, exceptionLabel, action) \
do \
{ \
if ( __builtin_expect(!(assertion), 0) ) \
{ \
{ \
action; \
} \
goto exceptionLabel; \
} \
} while ( 0 )
#endif
#else
#define cc_require_action(assertion, exceptionLabel, action) \
do \
{ \
if ( __builtin_expect(!(assertion), 0) ) \
{ \
__CC_DEBUG_REQUIRE_MESSAGE( \
__CC_DEBUG_ASSERT_COMPONENT_NAME_STRING, \
#assertion, #exceptionLabel, 0, __FILE__, __LINE__, 0); \
{ \
action; \
} \
goto exceptionLabel; \
} \
} while ( 0 )
#endif
#endif
#ifndef cc_require_or_return
#if (__CC_DEBUG_ASSERT_PRODUCTION_CODE) || (!CORECRYPTO_DEBUG_ENABLE_CC_REQUIRE_PRINTS)
#if defined(_WIN32) && defined (__clang__)
#define cc_require_or_return(assertion, value) \
do { \
if (!(assertion) ) { \
return value; \
} \
} while ( 0 )
#else
#define cc_require_or_return(assertion, value) \
do { \
if ( __builtin_expect(!(assertion), 0) ) { \
return value; \
} \
} while ( 0 )
#endif
#else
#define cc_require_or_return(assertion, value) \
do { \
if ( __builtin_expect(!(assertion), 0) ) { \
__CC_DEBUG_REQUIRE_MESSAGE(__CC_DEBUG_ASSERT_COMPONENT_NAME_STRING, \
#assertion, #exceptionLabel, 0, __FILE__, __LINE__, 0); \
return value; \
} \
} while ( 0 )
#endif
#endif
#endif /* _CORECRYPTO_CC_MACROS_H_ */

View file

@ -0,0 +1,339 @@
/* Copyright (c) (2010-2012,2014-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CC_PRIV_H_
#define _CORECRYPTO_CC_PRIV_H_
#include <corecrypto/cc.h>
CC_PTRCHECK_CAPABLE_HEADER()
#if !CC_EXCLAVEKIT
// Fork handlers for the stateful components of corecrypto.
void cc_atfork_prepare(void);
void cc_atfork_parent(void);
void cc_atfork_child(void);
#endif
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#ifndef __DECONST
#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var))
#endif
/* defines the following macros :
CC_ARRAY_LEN: returns the number of elements in an array
CC_ROR : Rotate Right 32 bits. Rotate count can be a variable.
CC_ROL : Rotate Left 32 bits. Rotate count can be a variable.
CC_RORc : Rotate Right 32 bits. Rotate count must be a constant.
CC_ROLc : Rotate Left 32 bits. Rotate count must be a constant.
CC_ROR64 : Rotate Right 64 bits. Rotate count can be a variable.
CC_ROL64 : Rotate Left 64 bits. Rotate count can be a variable.
CC_ROR64c : Rotate Right 64 bits. Rotate count must be a constant.
CC_ROL64c : Rotate Left 64 bits. Rotate count must be a constant.
CC_BSWAP : byte swap a 32 bits variable.
CC_H2BE32 : convert a 32 bits value between host and big endian order.
CC_H2LE32 : convert a 32 bits value between host and little endian order.
CC_BSWAP64 : byte swap a 64 bits variable
CC_H2BE64 : convert a 64 bits value between host and big endian order
CC_H2LE64 : convert a 64 bits value between host and little endian order
*/
// RTKitOSPlatform should replace CC_MEMCPY with memcpy
#define CC_MEMCPY(D,S,L) cc_memcpy((D),(S),(L))
#define CC_MEMMOVE(D,S,L) cc_memmove((D),(S),(L))
#define CC_MEMSET(D,V,L) cc_memset((D),(V),(L))
#if CC_EFI
void *cc_memcpy(void *dst, const void *src, size_t len);
#define cc_memcpy_nochk(dst, src, len) cc_memcpy((dst), (src), (len))
#elif __has_builtin(__builtin___memcpy_chk) && !defined(_MSC_VER) && !CC_SGX && !CC_ARM_ARCH_6M
#define cc_memcpy(dst, src, len) __builtin___memcpy_chk((dst), (src), (len), __builtin_object_size((dst), 1))
#define cc_memcpy_nochk(dst, src, len) __builtin___memcpy_chk((dst), (src), (len), __builtin_object_size((dst), 0))
#else
#define cc_memcpy(dst, src, len) memcpy((dst), (src), (len))
#define cc_memcpy_nochk(dst, src, len) memcpy((dst), (src), (len))
#endif
#if CC_EFI
void *cc_memmove(void *dst, const void *src, size_t len);
#elif __has_builtin(__builtin___memmove_chk) && !defined(_MSC_VER) && !CC_SGX && !CC_ARM_ARCH_6M
#define cc_memmove(dst, src, len) __builtin___memmove_chk((dst), (src), (len), __builtin_object_size((dst), 1))
#else
#define cc_memmove(dst, src, len) memmove((dst), (src), (len))
#endif
#if CC_EFI
void *cc_memset(void *dst, int val, size_t num);
#elif __has_builtin(__builtin___memset_chk) && !defined(_MSC_VER) && !CC_SGX && !CC_ARM_ARCH_6M
#define cc_memset(dst, val, len) __builtin___memset_chk((dst), (val), (len), __builtin_object_size((dst), 1))
#else
#define cc_memset(dst, val, len) memset((dst), (val), (len))
#endif
#define CC_ARRAY_LEN(x) (sizeof((x))/sizeof((x)[0]))
// MARK: - Loads and Store
// 64 bit load & store big endian
#if defined(__x86_64__) && !defined(_MSC_VER)
CC_INLINE void cc_store64_be(uint64_t x, uint8_t cc_sized_by(8) * y)
{
__asm__("bswapq %1 \n\t"
"movq %1, %0 \n\t"
"bswapq %1 \n\t"
: "=m"(*(y))
: "r"(x));
}
CC_INLINE uint64_t cc_load64_be(const uint8_t cc_sized_by(8) * y)
{
uint64_t x;
__asm__("movq %1, %0 \n\t"
"bswapq %0 \n\t"
: "=r"(x)
: "m"(*(y)));
return x;
}
#else
CC_INLINE void cc_store64_be(uint64_t x, uint8_t cc_sized_by(8) * y)
{
y[0] = (uint8_t)(x >> 56);
y[1] = (uint8_t)(x >> 48);
y[2] = (uint8_t)(x >> 40);
y[3] = (uint8_t)(x >> 32);
y[4] = (uint8_t)(x >> 24);
y[5] = (uint8_t)(x >> 16);
y[6] = (uint8_t)(x >> 8);
y[7] = (uint8_t)(x);
}
CC_INLINE uint64_t cc_load64_be(const uint8_t cc_sized_by(8) * y)
{
return (((uint64_t)(y[0])) << 56) | (((uint64_t)(y[1])) << 48) | (((uint64_t)(y[2])) << 40) | (((uint64_t)(y[3])) << 32) |
(((uint64_t)(y[4])) << 24) | (((uint64_t)(y[5])) << 16) | (((uint64_t)(y[6])) << 8) | ((uint64_t)(y[7]));
}
#endif
// 32 bit load & store big endian
#if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)
CC_INLINE void cc_store32_be(uint32_t x, uint8_t cc_sized_by(4) * y)
{
__asm__("bswapl %1 \n\t"
"movl %1, %0 \n\t"
"bswapl %1 \n\t"
: "=m"(*(y))
: "r"(x));
}
CC_INLINE uint32_t cc_load32_be(const uint8_t cc_sized_by(4) * y)
{
uint32_t x;
__asm__("movl %1, %0 \n\t"
"bswapl %0 \n\t"
: "=r"(x)
: "m"(*(y)));
return x;
}
#else
CC_INLINE void cc_store32_be(uint32_t x, uint8_t cc_sized_by(4) * y)
{
y[0] = (uint8_t)(x >> 24);
y[1] = (uint8_t)(x >> 16);
y[2] = (uint8_t)(x >> 8);
y[3] = (uint8_t)(x);
}
CC_INLINE uint32_t cc_load32_be(const uint8_t cc_sized_by(4) * y)
{
return (((uint32_t)(y[0])) << 24) | (((uint32_t)(y[1])) << 16) | (((uint32_t)(y[2])) << 8) | ((uint32_t)(y[3]));
}
#endif
CC_INLINE void cc_store16_be(uint16_t x, uint8_t cc_sized_by(2) * y)
{
y[0] = (uint8_t)(x >> 8);
y[1] = (uint8_t)(x);
}
CC_INLINE uint16_t cc_load16_be(const uint8_t cc_sized_by(2) * y)
{
return (uint16_t) (((uint16_t)(y[0])) << 8) | ((uint16_t)(y[1]));
}
// 64 bit load & store little endian
CC_INLINE void cc_store64_le(uint64_t x, uint8_t cc_sized_by(8) * y)
{
y[7] = (uint8_t)(x >> 56);
y[6] = (uint8_t)(x >> 48);
y[5] = (uint8_t)(x >> 40);
y[4] = (uint8_t)(x >> 32);
y[3] = (uint8_t)(x >> 24);
y[2] = (uint8_t)(x >> 16);
y[1] = (uint8_t)(x >> 8);
y[0] = (uint8_t)(x);
}
CC_INLINE uint64_t cc_load64_le(const uint8_t cc_sized_by(8) * y)
{
return (((uint64_t)(y[7])) << 56) | (((uint64_t)(y[6])) << 48) | (((uint64_t)(y[5])) << 40) | (((uint64_t)(y[4])) << 32) |
(((uint64_t)(y[3])) << 24) | (((uint64_t)(y[2])) << 16) | (((uint64_t)(y[1])) << 8) | ((uint64_t)(y[0]));
}
// 32 bit load & store little endian
CC_INLINE void cc_store32_le(uint32_t x, uint8_t cc_sized_by(4) * y)
{
y[3] = (uint8_t)(x >> 24);
y[2] = (uint8_t)(x >> 16);
y[1] = (uint8_t)(x >> 8);
y[0] = (uint8_t)(x);
}
CC_INLINE uint32_t cc_load32_le(const uint8_t cc_sized_by(4) * y)
{
return (((uint32_t)(y[3])) << 24) | (((uint32_t)(y[2])) << 16) | (((uint32_t)(y[1])) << 8) | ((uint32_t)(y[0]));
}
#if (CCN_UNIT_SIZE == 8)
#define cc_load_le cc_load64_le
#define cc_store_le cc_store64_le
#else
#define cc_load_le cc_load32_le
#define cc_store_le cc_store32_le
#endif
// MARK: - Byte Swaps
#if __has_builtin(__builtin_bswap32)
#define CC_BSWAP32(x) __builtin_bswap32(x)
#else
CC_INLINE uint32_t CC_BSWAP32(uint32_t x)
{
return
((x & 0xff000000) >> 24) |
((x & 0x00ff0000) >> 8) |
((x & 0x0000ff00) << 8) |
((x & 0x000000ff) << 24);
}
#endif
#if __has_builtin(__builtin_bswap64)
#define CC_BSWAP64(x) __builtin_bswap64(x)
#else
CC_INLINE uint64_t CC_BSWAP64(uint64_t x)
{
return
((x & 0xff00000000000000ULL) >> 56) |
((x & 0x00ff000000000000ULL) >> 40) |
((x & 0x0000ff0000000000ULL) >> 24) |
((x & 0x000000ff00000000ULL) >> 8) |
((x & 0x00000000ff000000ULL) << 8) |
((x & 0x0000000000ff0000ULL) << 24) |
((x & 0x000000000000ff00ULL) << 40) |
((x & 0x00000000000000ffULL) << 56);
}
#endif
#ifdef __LITTLE_ENDIAN__
#define CC_H2BE32(x) CC_BSWAP32(x)
#define CC_H2LE32(x) (x)
#define CC_H2BE64(x) CC_BSWAP64(x)
#define CC_H2LE64(x) (x)
#else
#define CC_H2BE32(x) (x)
#define CC_H2LE32(x) CC_BSWAP32(x)
#define CC_H2BE64(x) (x)
#define CC_H2LE64(x) CC_BSWAP64(x)
#endif
#define cc_ceiling(a,b) (((a)+((b)-1))/(b))
#define CC_BITLEN_TO_BYTELEN(x) cc_ceiling((x), 8)
#define CC_PROVIDES_ABORT (!(CC_BASEBAND || CC_EFI || CC_RTKITROM || CC_USE_SEPROM))
/*!
@function cc_abort
@abstract Abort execution unconditionally
*/
CC_NORETURN
void cc_abort(const char *msg);
/*!
@function cc_try_abort
@abstract Abort execution iff the platform provides a function like @p abort() or @p panic()
@discussion If the platform does not provide a means to abort execution, this function does nothing; therefore, callers should return an error code after calling this function.
*/
void cc_try_abort(const char *msg);
#if __has_builtin(__builtin_expect)
#define CC_LIKELY(cond) __builtin_expect(!!(cond), 1)
#define CC_UNLIKELY(cond) __builtin_expect(!!(cond), 0)
#else
#define CC_LIKELY(cond) cond
#define CC_UNLIKELY(cond) cond
#endif
#define cc_abort_if(cond, msg) \
do { \
if (CC_UNLIKELY(cond)) { \
cc_abort(msg); \
} \
} while (0)
void cc_try_abort_if(bool condition, const char *msg);
/*
Unfortunately, since we export this symbol, this declaration needs
to be in a public header to satisfy TAPI.
See fipspost_trace_priv.h for more details.
*/
extern const void *fipspost_trace_vtable;
// MARK: -- Deprecated macros
/*
Use `cc_store32_be`, `cc_store32_le`, `cc_store64_be`, `cc_store64_le`, and
`cc_load32_be`, `cc_load32_le`, `cc_load64_be`, `cc_load64_le` instead.
CC_STORE32_BE : store 32 bit value in big endian in unaligned buffer.
CC_STORE32_LE : store 32 bit value in little endian in unaligned buffer.
CC_STORE64_BE : store 64 bit value in big endian in unaligned buffer.
CC_STORE64_LE : store 64 bit value in little endian in unaligned buffer.
CC_LOAD32_BE : load 32 bit value in big endian from unaligned buffer.
CC_LOAD32_LE : load 32 bit value in little endian from unaligned buffer.
CC_LOAD64_BE : load 64 bit value in big endian from unaligned buffer.
CC_LOAD64_LE : load 64 bit value in little endian from unaligned buffer.
CC_READ_LE32 : read a 32 bits little endian value
CC_WRITE_LE32 : write a 32 bits little endian value
CC_WRITE_LE64 : write a 64 bits little endian value
*/
#define CC_STORE32_BE(x, y) cc_store32_be((uint32_t)(x), (uint8_t *)(y))
#define CC_STORE32_LE(x, y) cc_store32_le((uint32_t)(x), (uint8_t *)(y))
#define CC_STORE64_BE(x, y) cc_store64_be((uint64_t)(x), (uint8_t *)(y))
#define CC_STORE64_LE(x, y) cc_store64_le((uint64_t)(x), (uint8_t *)(y))
#define CC_LOAD32_BE(x, y) ((x) = cc_load32_be((uint8_t *)(y)))
#define CC_LOAD32_LE(x, y) ((x) = cc_load32_le((uint8_t *)(y)))
#define CC_LOAD64_BE(x, y) ((x) = cc_load64_be((uint8_t *)(y)))
#define CC_LOAD64_LE(x, y) ((x) = cc_load64_le((uint8_t *)(y)))
#define CC_READ_LE32(ptr) cc_load32_le((uint8_t *)(ptr))
#define CC_WRITE_LE32(ptr, x) cc_store32_le((uint32_t)(x), (uint8_t *)(ptr))
#define CC_WRITE_LE64(ptr, x) cc_store64_le((uint64_t)(x), (uint8_t *)(ptr))
#endif /* _CORECRYPTO_CC_PRIV_H_ */

View file

@ -0,0 +1,153 @@
/* Copyright (c) (2012,2014-2023) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef CORECRYPTO_CC_RUNTIME_CONFIG_H_
#define CORECRYPTO_CC_RUNTIME_CONFIG_H_
#include <corecrypto/cc_config.h>
#include <corecrypto/cc.h>
#if defined(__x86_64__) || defined(__i386__)
#define CC_HAS_DIT() (0)
#if CC_KERNEL
#include <i386/cpuid.h>
#define CC_HAS_RDRAND() ((cpuid_features() & CPUID_FEATURE_RDRAND) != 0)
#define CC_HAS_AESNI() ((cpuid_features() & CPUID_FEATURE_AES) != 0)
#define CC_HAS_SupplementalSSE3() ((cpuid_features() & CPUID_FEATURE_SSSE3) != 0)
#define CC_HAS_AVX1() ((cpuid_features() & CPUID_FEATURE_AVX1_0) != 0)
#define CC_HAS_AVX2() ((cpuid_info()->cpuid_leaf7_features & CPUID_LEAF7_FEATURE_AVX2) != 0)
#define CC_HAS_AVX512_AND_IN_KERNEL() ((cpuid_info()->cpuid_leaf7_features & CPUID_LEAF7_FEATURE_AVX512F) !=0)
#define CC_HAS_BMI2() ((cpuid_info()->cpuid_leaf7_features & CPUID_LEAF7_FEATURE_BMI2) != 0)
#define CC_HAS_ADX() ((cpuid_info()->cpuid_leaf7_features & CPUID_LEAF7_FEATURE_ADX) != 0)
#elif CC_DARWIN && CC_INTERNAL_SDK
#include <System/i386/cpu_capabilities.h>
#define CC_HAS_RDRAND() (_get_cpu_capabilities() & kHasRDRAND)
#define CC_HAS_AESNI() (_get_cpu_capabilities() & kHasAES)
#define CC_HAS_SupplementalSSE3() (_get_cpu_capabilities() & kHasSupplementalSSE3)
#define CC_HAS_AVX1() (_get_cpu_capabilities() & kHasAVX1_0)
#define CC_HAS_AVX2() (_get_cpu_capabilities() & kHasAVX2_0)
#define CC_HAS_AVX512_AND_IN_KERNEL() 0
#define CC_HAS_BMI2() (_get_cpu_capabilities() & kHasBMI2)
#define CC_HAS_ADX() (_get_cpu_capabilities() & kHasADX)
#elif CC_SGX
#include <cpuid.h>
#include <stdbool.h>
#include <stdint.h>
#define CPUID_REG_RAX 0
#define CPUID_REG_RBX 1
#define CPUID_REG_RCX 2
#define CPUID_REG_RDX 3
#define CPUID_FEATURE_AES 25
#define CPUID_FEATURE_SSE3 0
#define CPUID_FEATURE_AVX1 28
#define CPUID_FEATURE_LEAF7_AVX2 5
#define CPUID_FEATURE_LEAF7_BMI2 8
#define CPUID_FEATURE_RDRAND 30
#define CPUID_FEATURE_LEAF7_ADX 19
CC_INLINE bool _cpu_supports(uint64_t leaf, uint64_t subleaf, uint8_t cpuid_register, uint8_t bit) {
uint64_t registers[4] = {0};
registers[CPUID_REG_RAX] = leaf;
registers[CPUID_REG_RCX] = subleaf;
if (oe_emulate_cpuid(&registers[CPUID_REG_RAX], &registers[CPUID_REG_RBX], &registers[CPUID_REG_RCX], &registers[CPUID_REG_RDX])) {
return false;
}
return (registers[cpuid_register] >> bit) & 1;
}
#define CC_HAS_AESNI() _cpu_supports(1, 0, CPUID_REG_RCX, CPUID_FEATURE_AES)
#define CC_HAS_SupplementalSSE3() _cpu_supports(1, 0, CPUID_REG_RCX, CPUID_FEATURE_SSE3)
#define CC_HAS_AVX1() _cpu_supports(1, 0, CPUID_REG_RCX, CPUID_FEATURE_AVX1)
#define CC_HAS_AVX2() _cpu_supports(7, 0, CPUID_REG_RBX, CPUID_FEATURE_LEAF7_AVX2)
#define CC_HAS_AVX512_AND_IN_KERNEL() 0
#define CC_HAS_BMI2() _cpu_supports(7, 0, CPUID_REG_RBX, CPUID_FEATURE_LEAF7_BMI2)
#define CC_HAS_RDRAND() _cpu_supports(1, 0, CPUID_REG_RCX, CPUID_FEATURE_RDRAND)
#define CC_HAS_ADX() _cpu_supports(7, 0, CPUID_REG_RBX, CPUID_FEATURE_LEAF7_ADX)
#else
#define CC_HAS_AESNI() __builtin_cpu_supports("aes")
#define CC_HAS_SupplementalSSE3() __builtin_cpu_supports("ssse3")
#define CC_HAS_AVX1() __builtin_cpu_supports("avx")
#define CC_HAS_AVX2() __builtin_cpu_supports("avx2")
#define CC_HAS_AVX512_AND_IN_KERNEL() 0
#define CC_HAS_BMI2() __builtin_cpu_supports("bmi2")
#if CC_LINUX || !CC_INTERNAL_SDK
#include <cpuid.h>
CC_INLINE bool _cpu_supports_rdrand(void)
{
unsigned int eax, ebx, ecx, edx;
__cpuid(1, eax, ebx, ecx, edx);
return ecx & bit_RDRND;
}
CC_INLINE bool _cpu_supports_adx(void)
{
unsigned int eax, ebx, ecx, edx;
__cpuid_count(7, 0, eax, ebx, ecx, edx);
return ebx & bit_ADX;
}
#define CC_HAS_RDRAND() _cpu_supports_rdrand()
#define CC_HAS_ADX() _cpu_supports_adx()
#else
#define CC_HAS_RDRAND() 0
#define CC_HAS_ADX() 0
#endif
#endif
#endif // defined(__x86_64__) || defined(__i386__)
#if defined(__arm64__)
#if CC_TXM
#define CC_HAS_SHA512() (CC_ARM_FEATURE_SHA512)
#define CC_HAS_SHA3() (0)
extern bool cc_dit_supported(void);
#define CC_HAS_DIT() (cc_dit_supported())
#elif CC_DARWIN && CC_INTERNAL_SDK
#include <System/arm/cpu_capabilities.h>
#if __has_feature(address_sanitizer)
#define CC_COMMPAGE_CPU_CAPABILITIES \
(*((volatile __attribute__((address_space(1))) uint64_t *)_COMM_PAGE_CPU_CAPABILITIES64))
#else
#define CC_COMMPAGE_CPU_CAPABILITIES \
(*((volatile uint64_t *)_COMM_PAGE_CPU_CAPABILITIES64))
#endif
CC_INLINE bool _cpu_supports(uint64_t flag)
{
return CC_COMMPAGE_CPU_CAPABILITIES & flag;
}
#define CC_HAS_SHA512() _cpu_supports(kHasARMv82SHA512)
#define CC_HAS_SHA3() _cpu_supports(kHasARMv82SHA3)
#define CC_HAS_DIT() _cpu_supports(kHasFeatDIT)
#else
#define CC_HAS_SHA512() (CC_ARM_FEATURE_SHA512)
#define CC_HAS_SHA3() (0)
#define CC_HAS_DIT() (0)
#endif
#endif // defined(__arm64__)
#endif /* CORECRYPTO_CC_RUNTIME_CONFIG_H_ */

View file

@ -0,0 +1,119 @@
/* Copyright (c) (2010-2013,2015-2019,2021-2023) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCAES_H_
#define _CORECRYPTO_CCAES_H_
#include <corecrypto/cc_config.h>
#include <corecrypto/ccmode.h>
CC_PTRCHECK_CAPABLE_HEADER()
#define CCAES_BLOCK_SIZE 16
#define CCAES_KEY_SIZE_128 16
#define CCAES_KEY_SIZE_192 24
#define CCAES_KEY_SIZE_256 32
#define CCAES_CTR_MAX_PARALLEL_NBLOCKS 8
extern const struct ccmode_ecb ccaes_ltc_ecb_decrypt_mode;
extern const struct ccmode_ecb ccaes_ltc_ecb_encrypt_mode;
extern const struct ccmode_cbc ccaes_gladman_cbc_encrypt_mode;
extern const struct ccmode_cbc ccaes_gladman_cbc_decrypt_mode;
#if CCAES_ARM_ASM
extern const struct ccmode_ecb ccaes_arm_ecb_encrypt_mode;
extern const struct ccmode_ecb ccaes_arm_ecb_decrypt_mode;
extern const struct ccmode_cbc ccaes_arm_cbc_encrypt_mode;
extern const struct ccmode_cbc ccaes_arm_cbc_decrypt_mode;
extern const struct ccmode_xts ccaes_arm_xts_encrypt_mode;
extern const struct ccmode_xts ccaes_arm_xts_decrypt_mode;
extern const struct ccmode_cfb ccaes_arm_cfb_encrypt_mode;
extern const struct ccmode_cfb ccaes_arm_cfb_decrypt_mode;
extern const struct ccmode_ofb ccaes_arm_ofb_crypt_mode;
#endif
#if CCAES_INTEL_ASM
extern const struct ccmode_ecb ccaes_intel_ecb_encrypt_opt_mode;
extern const struct ccmode_ecb ccaes_intel_ecb_encrypt_aesni_mode;
extern const struct ccmode_ecb ccaes_intel_ecb_decrypt_opt_mode;
extern const struct ccmode_ecb ccaes_intel_ecb_decrypt_aesni_mode;
extern const struct ccmode_cbc ccaes_intel_cbc_encrypt_opt_mode;
extern const struct ccmode_cbc ccaes_intel_cbc_encrypt_aesni_mode;
extern const struct ccmode_cbc ccaes_intel_cbc_decrypt_opt_mode;
extern const struct ccmode_cbc ccaes_intel_cbc_decrypt_aesni_mode;
extern const struct ccmode_xts ccaes_intel_xts_encrypt_opt_mode;
extern const struct ccmode_xts ccaes_intel_xts_encrypt_aesni_mode;
extern const struct ccmode_xts ccaes_intel_xts_decrypt_opt_mode;
extern const struct ccmode_xts ccaes_intel_xts_decrypt_aesni_mode;
#endif
#if CC_USE_L4
extern const struct ccmode_cbc ccaes_skg_cbc_encrypt_mode;
extern const struct ccmode_cbc ccaes_skg_cbc_decrypt_mode;
extern const struct ccmode_ecb ccaes_skg_ecb_encrypt_mode;
extern const struct ccmode_ecb ccaes_skg_ecb_decrypt_mode;
extern const struct ccmode_ecb ccaes_trng_ecb_encrypt_mode;
#endif
/* Implementation Selectors: */
const struct ccmode_ecb *ccaes_ecb_encrypt_mode(void);
const struct ccmode_cbc *ccaes_cbc_encrypt_mode(void);
const struct ccmode_cfb *ccaes_cfb_encrypt_mode(void);
const struct ccmode_cfb8 *ccaes_cfb8_encrypt_mode(void);
const struct ccmode_xts *ccaes_xts_encrypt_mode(void);
const struct ccmode_gcm *ccaes_gcm_encrypt_mode(void);
const struct ccmode_ccm *ccaes_ccm_encrypt_mode(void);
const struct ccmode_ecb *ccaes_ecb_decrypt_mode(void);
const struct ccmode_cbc *ccaes_cbc_decrypt_mode(void);
const struct ccmode_cfb *ccaes_cfb_decrypt_mode(void);
const struct ccmode_cfb8 *ccaes_cfb8_decrypt_mode(void);
const struct ccmode_xts *ccaes_xts_decrypt_mode(void);
const struct ccmode_gcm *ccaes_gcm_decrypt_mode(void);
const struct ccmode_ccm *ccaes_ccm_decrypt_mode(void);
const struct ccmode_ctr *ccaes_ctr_crypt_mode(void);
const struct ccmode_ofb *ccaes_ofb_crypt_mode(void);
const struct ccmode_siv *ccaes_siv_encrypt_mode(void);
const struct ccmode_siv *ccaes_siv_decrypt_mode(void);
const struct ccmode_siv_hmac *ccaes_siv_hmac_sha256_encrypt_mode(void);
const struct ccmode_siv_hmac *ccaes_siv_hmac_sha256_decrypt_mode(void);
/*!
@function ccaes_unwind
@abstract "Unwind" an AES encryption key to the equivalent decryption key.
@param key_nbytes Length in bytes of both the input and output keys
@param key The input AES encryption key
@param out The output AES decryption key
@result @p CCERR_OK iff successful.
@discussion Only AES256 (i.e. 32-byte) keys are supported. This function is not necessary in typical AES usage; consult the maintainers before using it.
*/
int ccaes_unwind(size_t key_nbytes, const void *cc_sized_by(key_nbytes) key, void *cc_sized_by(key_nbytes) out);
#endif /* _CORECRYPTO_CCAES_H_ */

View file

@ -0,0 +1,86 @@
/* Copyright (c) (2010-2012,2015-2019,2021,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCASN1_H_
#define _CORECRYPTO_CCASN1_H_
#include <corecrypto/cc.h>
CC_PTRCHECK_CAPABLE_HEADER()
/* ASN.1 types for on the fly ASN.1 BER/DER encoding/decoding. Don't use
these with the ccder interface, use the CCDER_ types instead. */
enum {
CCASN1_EOL = 0x00,
CCASN1_BOOLEAN = 0x01,
CCASN1_INTEGER = 0x02,
CCASN1_BIT_STRING = 0x03,
CCASN1_OCTET_STRING = 0x04,
CCASN1_NULL = 0x05,
CCASN1_OBJECT_IDENTIFIER = 0x06,
CCASN1_OBJECT_DESCRIPTOR = 0x07,
/* External or instance-of 0x08 */
CCASN1_REAL = 0x09,
CCASN1_ENUMERATED = 0x0a,
CCASN1_EMBEDDED_PDV = 0x0b,
CCASN1_UTF8_STRING = 0x0c,
/* 0x0d */
/* 0x0e */
/* 0x0f */
CCASN1_SEQUENCE = 0x10,
CCASN1_SET = 0x11,
CCASN1_NUMERIC_STRING = 0x12,
CCASN1_PRINTABLE_STRING = 0x13,
CCASN1_T61_STRING = 0x14,
CCASN1_VIDEOTEX_STRING = 0x15,
CCASN1_IA5_STRING = 0x16,
CCASN1_UTC_TIME = 0x17,
CCASN1_GENERALIZED_TIME = 0x18,
CCASN1_GRAPHIC_STRING = 0x19,
CCASN1_VISIBLE_STRING = 0x1a,
CCASN1_GENERAL_STRING = 0x1b,
CCASN1_UNIVERSAL_STRING = 0x1c,
/* 0x1d */
CCASN1_BMP_STRING = 0x1e,
CCASN1_HIGH_TAG_NUMBER = 0x1f,
CCASN1_TELETEX_STRING = CCASN1_T61_STRING,
CCASN1_TAG_MASK = 0xff,
CCASN1_TAGNUM_MASK = 0x1f,
CCASN1_METHOD_MASK = 0x20,
CCASN1_PRIMITIVE = 0x00,
CCASN1_CONSTRUCTED = 0x20,
CCASN1_CLASS_MASK = 0xc0,
CCASN1_UNIVERSAL = 0x00,
CCASN1_APPLICATION = 0x40,
CCASN1_CONTEXT_SPECIFIC = 0x80,
CCASN1_PRIVATE = 0xc0,
CCASN1_CONSTRUCTED_SET = CCASN1_SET | CCASN1_CONSTRUCTED,
CCASN1_CONSTRUCTED_SEQUENCE = CCASN1_SEQUENCE | CCASN1_CONSTRUCTED,
};
typedef const unsigned char * cc_unsafe_indexable ccoid_t;
#define CCOID(oid) (oid)
/* Returns the size of an oid including its tag and length. */
CC_PURE CC_NONNULL((1))
size_t ccoid_size(ccoid_t oid);
CC_PURE CC_NONNULL((1))
const unsigned char *cc_indexable ccoid_payload(ccoid_t oid);
CC_PURE
bool ccoid_equal(ccoid_t oid1, ccoid_t oid2);
#endif /* _CORECRYPTO_CCASN1_H_ */

View file

@ -0,0 +1,298 @@
/* Copyright (c) (2016-2019,2021,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCCHACHA20POLY1305_H_
#define _CORECRYPTO_CCCHACHA20POLY1305_H_
#include <corecrypto/cc.h>
CC_PTRCHECK_CAPABLE_HEADER()
#define CCCHACHA20_KEY_NBYTES 32
#define CCCHACHA20_BLOCK_NBYTES 64
#define CCCHACHA20_BLOCK_NBITS (CCCHACHA20_BLOCK_NBYTES * 8)
#define CCCHACHA20_NONCE_NBYTES 12
typedef struct {
uint32_t state[16];
uint8_t buffer[CCCHACHA20_BLOCK_NBYTES];
size_t leftover;
} ccchacha20_ctx;
#define CCPOLY1305_TAG_NBYTES 16
#define CCPOLY1305_KEY_NBYTES 32
typedef struct {
uint32_t r0, r1, r2, r3, r4;
uint32_t s1, s2, s3, s4;
uint32_t h0, h1, h2, h3, h4;
uint8_t buf[16];
size_t buf_used;
uint8_t key[16];
} ccpoly1305_ctx;
/*!
@group ccchacha20poly1305
@abstract Encrypts and authenticates or decrypts and verifies data.
@discussion See RFC 7539 for details.
@warning The key-nonce pair must be unique per encryption.
@warning A single message can be at most (2^38 - 64) bytes in length.
The correct sequence of calls to encrypt is:
@code ccchacha20poly1305_init(...)
ccchacha20poly1305_setnonce(...)
ccchacha20poly1305_aad(...) (may be called zero or more times)
ccchacha20poly1305_encrypt(...) (may be called zero or more times)
ccchacha20poly1305_finalize(...)
To reuse the context for additional encryptions, follow this sequence:
@code ccchacha20poly1305_reset(...)
ccchacha20poly1305_setnonce(...)
ccchacha20poly1305_aad(...) (may be called zero or more times)
ccchacha20poly1305_encrypt(...) (may be called zero or more times)
ccchacha20poly1305_finalize(...)
To decrypt, follow this call sequence:
@code ccchacha20poly1305_init(...)
ccchacha20poly1305_setnonce(...)
ccchacha20poly1305_aad(...) (may be called zero or more times)
ccchacha20poly1305_decrypt(...) (may be called zero or more times)
ccchacha20poly1305_verify(...) (returns zero on successful decryption)
To reuse the context for additional encryptions, follow this sequence:
@code ccchacha20poly1305_reset(...)
ccchacha20poly1305_setnonce(...)
ccchacha20poly1305_aad(...) (may be called zero or more times)
ccchacha20poly1305_decrypt(...) (may be called zero or more times)
ccchacha20poly1305_verify(...) (returns zero on successful decryption)
*/
#define CCCHACHA20POLY1305_KEY_NBYTES (CCCHACHA20_KEY_NBYTES)
#define CCCHACHA20POLY1305_NONCE_NBYTES (CCCHACHA20_NONCE_NBYTES)
#define CCCHACHA20POLY1305_TAG_NBYTES (CCPOLY1305_TAG_NBYTES)
/* (2^32 - 1) blocks */
/* (2^38 - 64) bytes */
/* (2^41 - 512) bits */
/* Exceeding this figure breaks confidentiality and authenticity. */
#define CCCHACHA20POLY1305_TEXT_MAX_NBYTES ((1ULL << 38) - 64ULL)
#define CCCHACHA20POLY1305_STATE_SETNONCE 1
#define CCCHACHA20POLY1305_STATE_AAD 2
#define CCCHACHA20POLY1305_STATE_ENCRYPT 3
#define CCCHACHA20POLY1305_STATE_DECRYPT 4
#define CCCHACHA20POLY1305_STATE_FINAL 5
typedef struct {
ccchacha20_ctx chacha20_ctx;
ccpoly1305_ctx poly1305_ctx;
uint64_t aad_nbytes;
uint64_t text_nbytes;
uint8_t state;
} ccchacha20poly1305_ctx;
// This is just a stub right now.
// Eventually we will optimize by platform.
struct ccchacha20poly1305_info {
};
const struct ccchacha20poly1305_info *ccchacha20poly1305_info(void);
/*!
@function ccchacha20poly1305_init
@abstract Initialize a chacha20poly1305 context.
@param info Implementation descriptor
@param ctx Context for this instance
@param key Secret chacha20 key
@result 0 iff successful.
@discussion The key is 32 bytes in length.
@warning The key-nonce pair must be unique per encryption.
*/
int ccchacha20poly1305_init(const struct ccchacha20poly1305_info *info, ccchacha20poly1305_ctx *ctx, const uint8_t *cc_counted_by(CCCHACHA20POLY1305_KEY_NBYTES) key);
/*!
@function ccchacha20poly1305_reset
@abstract Reset a chacha20poly1305 context for reuse.
@param info Implementation descriptor
@param ctx Context for this instance
@result 0 iff successful.
*/
int ccchacha20poly1305_reset(const struct ccchacha20poly1305_info *info, ccchacha20poly1305_ctx *ctx);
/*!
@function ccchacha20poly1305_setnonce
@abstract Set the nonce for encryption or decryption.
@param info Implementation descriptor
@param ctx Context for this instance
@param nonce Unique nonce per encryption
@result 0 iff successful.
@discussion The nonce is 12 bytes in length.
@warning The key-nonce pair must be unique per encryption.
*/
int ccchacha20poly1305_setnonce(const struct ccchacha20poly1305_info *info, ccchacha20poly1305_ctx *ctx, const uint8_t *cc_counted_by(CCCHACHA20POLY1305_NONCE_NBYTES) nonce);
int ccchacha20poly1305_incnonce(const struct ccchacha20poly1305_info *info, ccchacha20poly1305_ctx *ctx, uint8_t *cc_counted_by(CCCHACHA20POLY1305_NONCE_NBYTES) nonce);
/*!
@function ccchacha20poly1305_aad
@abstract Authenticate additional data.
@param info Descriptor for the mode
@param ctx Context for this instance
@param nbytes Length of the additional data in bytes
@param aad Additional data to authenticate
@result 0 iff successful.
@discussion This is typically used to authenticate data that cannot be encrypted (e.g. packet headers).
This function may be called zero or more times.
*/
int ccchacha20poly1305_aad(const struct ccchacha20poly1305_info *info, ccchacha20poly1305_ctx *ctx, size_t nbytes, const void *cc_sized_by(nbytes) aad);
/*!
@function ccchacha20poly1305_encrypt
@abstract Encrypt data.
@param info Descriptor for the mode
@param ctx Context for this instance
@param nbytes Length of the plaintext in bytes
@param ptext Input plaintext
@param ctext Output ciphertext
@result 0 iff successful.
@discussion In-place processing is supported.
This function may be called zero or more times.
*/
int ccchacha20poly1305_encrypt(const struct ccchacha20poly1305_info *info, ccchacha20poly1305_ctx *ctx, size_t nbytes, const void *cc_sized_by(nbytes) ptext, void *cc_sized_by(nbytes) ctext);
/*!
@function ccchacha20poly1305_finalize
@abstract Finalize encryption.
@param info Descriptor for the mode
@param ctx Context for this instance
@param tag Generated authentication tag
@result 0 iff successful.
@discussion The generated tag is 16 bytes in length.
*/
int ccchacha20poly1305_finalize(const struct ccchacha20poly1305_info *info, ccchacha20poly1305_ctx *ctx, uint8_t *cc_counted_by(CCCHACHA20POLY1305_TAG_NBYTES) tag);
/*!
@function ccchacha20poly1305_decrypt
@abstract Decrypt data.
@param info Descriptor for the mode
@param ctx Context for this instance
@param nbytes Length of the ciphertext in bytes
@param ctext Input ciphertext
@param ptext Output plaintext
@result 0 iff successful.
@discussion In-place processing is supported.
This function may be called zero or more times.
*/
int ccchacha20poly1305_decrypt(const struct ccchacha20poly1305_info *info, ccchacha20poly1305_ctx *ctx, size_t nbytes, const void *cc_sized_by(nbytes) ctext, void *cc_sized_by(nbytes) ptext);
/*!
@function ccchacha20poly1305_verify
@abstract Verify authenticity.
@param info Descriptor for the mode
@param ctx Context for this instance
@param tag Expected authentication tag
@result 0 iff authentic and otherwise successful.
@discussion The expected tag is 16 bytes in length.
*/
int ccchacha20poly1305_verify(const struct ccchacha20poly1305_info *info, ccchacha20poly1305_ctx *ctx, const uint8_t *cc_counted_by(CCCHACHA20POLY1305_TAG_NBYTES) tag);
/*!
@function ccchacha20poly1305_encrypt_oneshot
@abstract Encrypt with chacha20poly1305.
@param info Descriptor for the mode
@param key Secret chacha20 key
@param nonce Unique nonce per encryption
@param aad_nbytes Length of the additional data in bytes
@param aad Additional data to authenticate
@param ptext_nbytes Length of the plaintext in bytes
@param ptext Input plaintext
@param ctext Output ciphertext
@param tag Generated authentication tag
@discussion See RFC 7539 for details.
The key is 32 bytes in length.
The nonce is 12 bytes in length.
The generated tag is 16 bytes in length.
In-place processing is supported.
@warning The key-nonce pair must be unique per encryption.
@warning A single message can be at most (2^38 - 64) bytes in length.
*/
int ccchacha20poly1305_encrypt_oneshot(const struct ccchacha20poly1305_info *info, const uint8_t *cc_counted_by(CCCHACHA20POLY1305_KEY_NBYTES) key, const uint8_t *cc_counted_by(CCCHACHA20POLY1305_NONCE_NBYTES) nonce, size_t aad_nbytes, const void *cc_sized_by(aad_nbytes) aad, size_t ptext_nbytes, const void *cc_sized_by(ptext_nbytes) ptext, void *cc_sized_by(ptext_nbytes) ctext, uint8_t *cc_counted_by(CCCHACHA20POLY1305_TAG_NBYTES) tag);
/*!
@function ccchacha20poly1305_decrypt_oneshot
@abstract Decrypt with chacha20poly1305.
@param info Descriptor for the mode
@param key Secret chacha20 key
@param nonce Unique nonce per encryption
@param aad_nbytes Length of the additional data in bytes
@param aad Additional data to authenticate
@param ctext_nbytes Length of the ciphertext in bytes
@param ctext Input ciphertext
@param ptext Output plaintext
@param tag Expected authentication tag
@discussion See RFC 7539 for details.
The key is 32 bytes in length.
The nonce is 12 bytes in length.
The generated tag is 16 bytes in length.
In-place processing is supported.
*/
int ccchacha20poly1305_decrypt_oneshot(const struct ccchacha20poly1305_info *info, const uint8_t *cc_counted_by(CCCHACHA20POLY1305_KEY_NBYTES) key, const uint8_t *cc_counted_by(CCCHACHA20POLY1305_NONCE_NBYTES) nonce, size_t aad_nbytes, const void *cc_sized_by(aad_nbytes) aad, size_t ctext_nbytes, const void *cc_sized_by(ctext_nbytes) ctext, void *cc_sized_by(ctext_nbytes) ptext, const uint8_t *cc_counted_by(CCCHACHA20POLY1305_TAG_NBYTES) tag);
#endif

View file

@ -0,0 +1,182 @@
/* Copyright (c) (2013-2017,2019,2021,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCCMAC_H_
#define _CORECRYPTO_CCCMAC_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccmode.h>
#include <corecrypto/ccaes.h>
CC_PTRCHECK_CAPABLE_HEADER()
#define CMAC_BLOCKSIZE 16
struct cccmac_ctx {
uint8_t k1[CMAC_BLOCKSIZE];
uint8_t k2[CMAC_BLOCKSIZE];
uint8_t block[CMAC_BLOCKSIZE];
size_t block_nbytes; // Number of byte occupied in block
size_t cumulated_nbytes; // Total size processed
const struct ccmode_cbc *cbc;
uint8_t ctx[1];
} CC_ALIGNED(8);// cccmac_ctx_hdr;
typedef struct cccmac_ctx* cccmac_ctx_t;
#define cccmac_hdr_size sizeof(struct cccmac_ctx)
#define cccmac_iv_size(_mode_) ((_mode_)->block_size)
#define cccmac_cbc_size(_mode_) ((_mode_)->size)
#define cccmac_ctx_size(_mode_) (cccmac_hdr_size + cccmac_iv_size(_mode_) + cccmac_cbc_size(_mode_))
#define cccmac_ctx_n(_mode_) ccn_nof_size(cccmac_ctx_size(_mode_))
#define cccmac_mode_decl(_mode_, _name_) cc_ctx_decl_vla(struct cccmac_ctx, cccmac_ctx_size(_mode_), _name_)
#define cccmac_mode_clear(_mode_, _name_) cc_clear(cccmac_ctx_size(_mode_), _name_)
/* Return a cccbc_ctx * which can be accesed with the macros in ccmode.h */
#define cccmac_mode_ctx_start(_mode_, HC) (HC->ctx)
#define CCCMAC_HDR(HC) (HC)
#define cccmac_mode_sym_ctx(_mode_, HC) (cccbc_ctx *)(cccmac_mode_ctx_start(_mode_, HC))
#define cccmac_mode_iv(_mode_, HC) (cccbc_iv *)(cccmac_mode_ctx_start(_mode_, HC)+cccmac_cbc_size(_mode_))
#define cccmac_k1(HC) (CCCMAC_HDR(HC)->k1)
#define cccmac_k2(HC) (CCCMAC_HDR(HC)->k2)
#define cccmac_block(HC) (CCCMAC_HDR(HC)->block)
#define cccmac_cbc(HC) (CCCMAC_HDR(HC)->cbc)
#define cccmac_block_nbytes(HC) (CCCMAC_HDR(HC)->block_nbytes)
#define cccmac_cumulated_nbytes(HC) (CCCMAC_HDR(HC)->cumulated_nbytes)
/* CMAC as defined in NIST SP800-38B - 2005 */
/* =============================================================================
ONE SHOT
==============================================================================*/
/*!
@function cccmac_one_shot_generate
@abstract CMAC generation in one call
@param cbc CBC and block cipher specification
@param key_nbytes Length of the key in bytes
@param key Pointer to the key of length key_nbytes
@param data_nbytes Length of the data in bytes
@param data Pointer to the data in bytes
@param mac_nbytes Length in byte of the mac, > 0
@param mac Output of length cbc->block_size
@result 0 iff successful.
@discussion Only supports CMAC_BLOCKSIZE block ciphers
*/
int cccmac_one_shot_generate(const struct ccmode_cbc *cbc,
size_t key_nbytes, const void *cc_sized_by(key_nbytes) key,
size_t data_nbytes, const void *cc_sized_by(data_nbytes) data,
size_t mac_nbytes, void *cc_sized_by(mac_nbytes) mac);
/*!
@function cccmac_one_shot_verify
@abstract CMAC verification in one call
@param cbc CBC and block cipher specification
@param key_nbytes Length of the key in bytes
@param key Pointer to the key of length key_nbytes
@param data_nbytes Length of the data in bytes
@param data Pointer to the data in bytes
@param expected_mac_nbytes Length in byte of the mac, > 0
@param expected_mac Mac value expected
@result 0 iff successful.
@discussion Only supports CMAC_BLOCKSIZE block ciphers
*/
int cccmac_one_shot_verify(const struct ccmode_cbc *cbc,
size_t key_nbytes, const void *cc_sized_by(key_nbytes) key,
size_t data_nbytes, const void *cc_sized_by(data_nbytes) data,
size_t expected_mac_nbytes, const void *cc_sized_by(expected_mac_nbytes) expected_mac);
/* =============================================================================
STREAMING
Init - Update - Final
==============================================================================*/
/*!
@function cccmac_init
@abstract Init CMAC context with CBC mode and key
@param cbc CBC and block cipher specification
@param ctx Context use to store internal state
@param key_nbytes Length of the key in bytes
@param key Full key
@result 0 iff successful.
@discussion Only supports CMAC_BLOCKSIZE block ciphers
*/
int cccmac_init(const struct ccmode_cbc *cbc,
cccmac_ctx_t ctx,
size_t key_nbytes, const void *cc_sized_by(key_nbytes) key);
/*!
@function cccmac_update
@abstract Process data
@param ctx Context use to store internal state
@param data_nbytes Length in byte of the data
@param data Data to process
@result 0 iff successful.
@discussion Only supports CMAC_BLOCKSIZE block ciphers
*/
int cccmac_update(cccmac_ctx_t ctx,
size_t data_nbytes, const void *cc_sized_by(data_nbytes) data);
/*!
@function cccmac_final_generate
@abstract Final step for generation
@param ctx Context use to store internal state
@param mac_nbytes Length in byte of the mac, > 0
@param mac Output of length mac_nbytes
@result 0 iff successful.
@discussion Only supports CMAC_BLOCKSIZE block ciphers
*/
int cccmac_final_generate(cccmac_ctx_t ctx,
size_t mac_nbytes, void *cc_sized_by(mac_nbytes) mac);
/*!
@function cccmac_final_verify
@abstract Final step and verification
@param ctx Context use to store internal state
@param expected_mac_nbytes Length in byte of the mac, > 0
@param expected_mac Mac value expected
@result 0 iff successful.
@discussion Only supports CMAC_BLOCKSIZE block ciphers
*/
int cccmac_final_verify(cccmac_ctx_t ctx,
size_t expected_mac_nbytes, const void *cc_sized_by(expected_mac_nbytes) expected_mac);
#endif // _CORECRYPTO_CCCMAC_H_

View file

@ -0,0 +1,411 @@
/* Copyright (c) (2012-2019,2021,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCDER_H_
#define _CORECRYPTO_CCDER_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccasn1.h>
#include <corecrypto/ccn.h>
#include <corecrypto/ccder_blob.h>
/* DER types to be used with ccder_decode and ccder_encode functions. */
#define CCDER_EOL CCASN1_EOL
#define CCDER_BOOLEAN CCASN1_BOOLEAN
#define CCDER_INTEGER CCASN1_INTEGER
#define CCDER_BIT_STRING CCASN1_BIT_STRING
#define CCDER_OCTET_STRING CCASN1_OCTET_STRING
#define CCDER_NULL CCASN1_NULL
#define CCDER_OBJECT_IDENTIFIER CCASN1_OBJECT_IDENTIFIER
#define CCDER_OBJECT_DESCRIPTOR CCASN1_OBJECT_DESCRIPTOR
/* External or instance-of 0x08 */
#define CCDER_REAL CCASN1_REAL
#define CCDER_ENUMERATED CCASN1_ENUMERATED
#define CCDER_EMBEDDED_PDV CCASN1_EMBEDDED_PDV
#define CCDER_UTF8_STRING CCASN1_UTF8_STRING
/* 0x0d */
/* 0x0e */
/* 0x0f */
#define CCDER_SEQUENCE CCASN1_SEQUENCE
#define CCDER_SET CCASN1_SET
#define CCDER_NUMERIC_STRING CCASN1_NUMERIC_STRING
#define CCDER_PRINTABLE_STRING CCASN1_PRINTABLE_STRING
#define CCDER_T61_STRING CCASN1_T61_STRING
#define CCDER_VIDEOTEX_STRING CCASN1_VIDEOTEX_STRING
#define CCDER_IA5_STRING CCASN1_IA5_STRING
#define CCDER_UTC_TIME CCASN1_UTC_TIME
#define CCDER_GENERALIZED_TIME CCASN1_GENERALIZED_TIME
#define CCDER_GRAPHIC_STRING CCASN1_GRAPHIC_STRING
#define CCDER_VISIBLE_STRING CCASN1_VISIBLE_STRING
#define CCDER_GENERAL_STRING CCASN1_GENERAL_STRING
#define CCDER_UNIVERSAL_STRING CCASN1_UNIVERSAL_STRING
/* 0x1d */
#define CCDER_BMP_STRING CCASN1_BMP_STRING
#define CCDER_HIGH_TAG_NUMBER CCASN1_HIGH_TAG_NUMBER
#define CCDER_TELETEX_STRING CCDER_T61_STRING
#ifdef CCDER_MULTIBYTE_TAGS
#define CCDER_TAG_MASK ((ccder_tag)~0)
#define CCDER_TAGNUM_MASK ((ccder_tag) ~((ccder_tag)7 << (sizeof(ccder_tag) * 8 - 3)))
#define CCDER_METHOD_MASK ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 3))
#define CCDER_PRIMITIVE ((ccder_tag)0 << (sizeof(ccder_tag) * 8 - 3))
#define CCDER_CONSTRUCTED ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 3))
#define CCDER_CLASS_MASK ((ccder_tag)3 << (sizeof(ccder_tag) * 8 - 2))
#define CCDER_UNIVERSAL ((ccder_tag)0 << (sizeof(ccder_tag) * 8 - 2))
#define CCDER_APPLICATION ((ccder_tag)1 << (sizeof(ccder_tag) * 8 - 2))
#define CCDER_CONTEXT_SPECIFIC ((ccder_tag)2 << (sizeof(ccder_tag) * 8 - 2))
#define CCDER_PRIVATE ((ccder_tag)3 << (sizeof(ccder_tag) * 8 - 2))
#else /* !CCDER_MULTIBYTE_TAGS */
#define CCDER_TAG_MASK CCASN1_TAG_MASK
#define CCDER_TAGNUM_MASK CCASN1_TAGNUM_MASK
#define CCDER_METHOD_MASK CCASN1_METHOD_MASK
#define CCDER_PRIMITIVE CCASN1_PRIMITIVE
#define CCDER_CONSTRUCTED CCASN1_CONSTRUCTED
#define CCDER_CLASS_MASK CCASN1_CLASS_MASK
#define CCDER_UNIVERSAL CCASN1_UNIVERSAL
#define CCDER_APPLICATION CCASN1_APPLICATION
#define CCDER_CONTEXT_SPECIFIC CCASN1_CONTEXT_SPECIFIC
#define CCDER_PRIVATE CCASN1_PRIVATE
#endif /* !CCDER_MULTIBYTE_TAGS */
#define CCDER_CONSTRUCTED_SET (CCDER_SET | CCDER_CONSTRUCTED)
#define CCDER_CONSTRUCTED_SEQUENCE (CCDER_SEQUENCE | CCDER_CONSTRUCTED)
// MARK: - ccder_sizeof_ functions
/* Returns the size of an asn1 encoded item of length l in bytes. */
CC_CONST
size_t ccder_sizeof(ccder_tag tag, size_t len);
CC_NONNULL_ALL
size_t ccder_sizeof_overflow(ccder_tag tag, size_t nbytes, bool *overflowed);
CC_PURE
size_t ccder_sizeof_implicit_integer(ccder_tag implicit_tag, cc_size n, const cc_unit *s);
CC_PURE
size_t ccder_sizeof_implicit_octet_string(ccder_tag implicit_tag, cc_size n, const cc_unit *s);
CC_CONST
size_t ccder_sizeof_implicit_raw_octet_string(ccder_tag implicit_tag, size_t s_size);
CC_NONNULL_ALL
size_t ccder_sizeof_implicit_raw_octet_string_overflow(ccder_tag implicit_tag, size_t s_size, bool *overflowed);
CC_CONST
size_t ccder_sizeof_implicit_uint64(ccder_tag implicit_tag, uint64_t value);
CC_PURE
size_t ccder_sizeof_integer(cc_size n, const cc_unit *s);
CC_CONST
size_t ccder_sizeof_len(size_t len);
CC_PURE
size_t ccder_sizeof_octet_string(cc_size n, const cc_unit *s);
CC_PURE
size_t ccder_sizeof_oid(ccoid_t oid);
CC_CONST
size_t ccder_sizeof_raw_octet_string(size_t s_size);
CC_CONST
size_t ccder_sizeof_tag(ccder_tag tag);
CC_CONST
size_t ccder_sizeof_uint64(uint64_t value);
CC_PURE
size_t ccder_sizeof_eckey(size_t priv_size, ccoid_t oid, size_t pub_size);
/* alias of ccder_sizeof_eckey */
CC_PURE
size_t ccder_encode_eckey_size(size_t priv_size, ccoid_t oid, size_t pub_size);
/* All of the original functions are unavailable in a ptrcheck build. */
// MARK: - Encode/decode functions, unavailable in ptrcheck
/* Encode a tag backwards, der_end should point to one byte past the end of
destination for the tag, returns a pointer to the first byte of the tag.
Returns NULL if there is an encoding error. */
CC_NONNULL((2)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_tag(ccder_tag tag, const uint8_t *der, uint8_t *der_end);
/* Returns a pointer to the start of the len field. returns NULL if there
is an encoding error. */
CC_NONNULL((2)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_len(size_t len, const uint8_t *der, uint8_t *der_end);
/* der_end should point to the first byte of the content of this der item. */
CC_NONNULL((3)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_tl(ccder_tag tag, size_t len, const uint8_t *der, uint8_t *der_end);
CC_PURE CC_NONNULL((2)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_body_nocopy(size_t size, const uint8_t *der, uint8_t *der_end);
/* Encode the tag and length of a constructed object. der is the lower
bound, der_end is one byte paste where we want to write the length and
body_end is one byte past the end of the body of the der object we are
encoding the tag and length of. */
CC_NONNULL((2, 3)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_constructed_tl(ccder_tag tag, const uint8_t *body_end, const uint8_t *der, uint8_t *der_end);
/* Encodes oid into der and returns der + ccder_sizeof_oid(oid). */
CC_NONNULL((1, 2)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_oid(ccoid_t oid, const uint8_t *der, uint8_t *der_end);
CC_NONNULL((3, 4)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_implicit_integer(ccder_tag implicit_tag, cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end);
CC_NONNULL((2, 3)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_integer(cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end);
CC_NONNULL((3)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_implicit_uint64(ccder_tag implicit_tag, uint64_t value, const uint8_t *der, uint8_t *der_end);
CC_NONNULL((2)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_uint64(uint64_t value, const uint8_t *der, uint8_t *der_end);
CC_NONNULL((3, 4)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_implicit_octet_string(ccder_tag implicit_tag, cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end);
CC_NONNULL((2, 3)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_octet_string(cc_size n, const cc_unit *s, const uint8_t *der, uint8_t *der_end);
CC_NONNULL((3, 4)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_implicit_raw_octet_string(ccder_tag implicit_tag,
size_t s_size,
const uint8_t *s,
const uint8_t *der,
uint8_t *der_end);
CC_NONNULL((2, 3)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_raw_octet_string(size_t s_size, const uint8_t *s, const uint8_t *der, uint8_t *der_end);
CC_NONNULL((2, 5, 6)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_eckey(size_t priv_size,
const uint8_t *priv_key,
ccoid_t oid,
size_t pub_size,
const uint8_t *pub_key,
uint8_t *der,
uint8_t *der_end);
/* ccder_encode_body COPIES the body into the der.
It's inefficient especially when you already have to convert to get to
the form for the body.
see encode integer for the right way to unify conversion and insertion */
CC_NONNULL((3)) cc_ptrcheck_unavailable()
uint8_t *ccder_encode_body(size_t size, const uint8_t *body, const uint8_t *der, uint8_t *der_end);
/* Returns a pointer to the start of the length field, and returns the decoded tag in tag.
returns NULL if there is a decoding error. */
CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_tag(ccder_tag *tagp, const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_len(size_t *lenp, const uint8_t *der, const uint8_t *der_end);
/*!
@function ccder_decode_len_strict
@abstract Decode the length of a DER encoded item
@param lenp Pointer to the length of the DER item
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result First byte after the parsed length or NULL if the length is not valid (i.e. when the length isn't DER encoded)
*/
CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_len_strict(size_t *lenp, const uint8_t *der, const uint8_t *der_end);
/* Returns a pointer to the start of the der object, and returns the length in len.
returns NULL if there is a decoding error. */
CC_NONNULL((2, 4)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_tl(ccder_tag expected_tag, size_t *lenp, const uint8_t *der, const uint8_t *der_end);
/*!
@function ccder_decode_tl_strict
@abstract Decode a tag and length from a DER object given an expected tag.
@param expected_tag Tag of expected DER object pointed to by `der`
@param lenp Output length of DER object
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result Pointer to the DER object with the length contained in `lenp` otherwise NULL.
*/
CC_NONNULL((2, 4)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_tl_strict(ccder_tag expected_tag, size_t *lenp, const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((2, 4)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_constructed_tl(ccder_tag expected_tag,
const uint8_t **body_end,
const uint8_t *der,
const uint8_t *der_end);
/*!
@function ccder_decode_constructed_tl_strict
@abstract Decode a tag and length from a contstructed DER object given an expected tag.
@param expected_tag Tag of expected DER object pointed to by `der`
@param body_end Pointer to hold the end of the sequence
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result Pointer to the first DER object within the constructed object and the length of the total constructed object
contained in `lenp`; NULL otherwise.
*/
CC_NONNULL((2, 4)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_constructed_tl_strict(ccder_tag expected_tag, const uint8_t **body_end, const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_sequence_tl(const uint8_t **body_end, const uint8_t *der, const uint8_t *der_end);
/*!
@function ccder_decode_sequence_tl_strict
@abstract Decode a DER sequence.
@param body_end Pointer to hold the end of the sequence
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result Pointer to the first DER object within the sequence otherwise NULL.
*/
CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_sequence_tl_strict(const uint8_t **body_end, const uint8_t *der, const uint8_t *der_end);
/*!
@function ccder_decode_uint_n
@abstract length in cc_unit of a der unsigned integer after skipping the leading zeroes
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@param n Output the number of cc_unit required to represent the number
@result First byte after the parsed integer or
NULL if the integer is not valid (negative) or reach der_end when reading the integer
*/
CC_NONNULL((3)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_uint_n(cc_size *n, const uint8_t *der, const uint8_t *der_end);
/*!
@function ccder_decode_uint
@abstract Represent in cc_unit a ber unsigned integer after skipping the leading zeroes
@param der Beginning of input BER buffer
@param der_end End of input BER buffer
@param n Number of cc_unit allocated for r
@param r Allocated array of cc_unit to copy the integer into.
@result First byte after the parsed integer or
NULL if the integer is not valid (negative)
reach der_end when reading the integer
n cc_unit is not enough to represent the integer
*/
CC_NONNULL((4)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_uint(cc_size n, cc_unit *r, const uint8_t *der, const uint8_t *der_end);
/*!
@function ccder_decode_uint_strict
@abstract Represent in cc_unit a der unsigned integer after skipping the leading zeroes
@param n Number of cc_unit allocated for r
@param r Allocated array of cc_unit to copy the integer into.
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result First byte after the parsed integer or NULL if the integer is not valid.
*/
CC_NONNULL((4)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_uint_strict(cc_size n, cc_unit *r, const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((3)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_uint64(uint64_t *r, const uint8_t *der, const uint8_t *der_end);
/* Decode SEQUENCE { r, s -- (unsigned)integer } in ber into r and s.
Returns NULL on decode errors, returns pointer just past the end of the
sequence of integers otherwise. */
CC_NONNULL((2, 3, 5)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_seqii(cc_size n, cc_unit *r, cc_unit *s, const uint8_t *der, const uint8_t *der_end);
/*!
@function ccder_decode_seqii_strict
@abstract Parse a DER sequence of two integers.
@param n The maximum unit size of the integers.
@param r First integer output
@param s Second integer output
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result Null on error, otherwise a pointer just past the end of the sequence buffer
*/
CC_NONNULL((2, 3, 5)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_seqii_strict(cc_size n, cc_unit *r, cc_unit *s, const uint8_t *der, const uint8_t *der_end);
/*!
@function ccder_decode_oid
@abstract Parse a DER sequence representing an oid.
@param oidp Pointer to OID
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result Null on error, otherwise a pointer just past the end of the sequence buffer.
@warning In case of error, *oidp is set to NULL.
Otherwise, *oidp is a pointer to a buffer of "unsigned char" of size >= 2.
*/
CC_NONNULL((1, 3)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_oid(ccoid_t *oidp, const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((1, 2, 4)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_bitstring(const uint8_t **bit_string, size_t *bit_length, const uint8_t *der, const uint8_t *der_end);
CC_NONNULL((1, 2, 3, 4, 5, 6, 7)) cc_ptrcheck_unavailable()
const uint8_t *ccder_decode_eckey(uint64_t *version,
size_t *priv_size,
const uint8_t **priv_key,
ccoid_t *oid,
size_t *pub_size,
const uint8_t **pub_key,
const uint8_t *der,
const uint8_t *der_end);
// MARK: -
#define CC_EC_OID_SECP192R1 \
{ \
((unsigned char *)"\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x01") \
}
#define CC_EC_OID_SECP256R1 \
{ \
((unsigned char *)"\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07") \
}
#define CC_EC_OID_SECP224R1 \
{ \
((unsigned char *)"\x06\x05\x2B\x81\x04\x00\x21") \
}
#define CC_EC_OID_SECP384R1 \
{ \
((unsigned char *)"\x06\x05\x2B\x81\x04\x00\x22") \
}
#define CC_EC_OID_SECP521R1 \
{ \
((unsigned char *)"\x06\x05\x2B\x81\x04\x00\x23") \
}
#endif /* _CORECRYPTO_CCDER_H_ */

View file

@ -0,0 +1,148 @@
/* Copyright (c) (2021,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCDER_BLOB_H_
#define _CORECRYPTO_CCDER_BLOB_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccasn1.h>
#include <corecrypto/ccn.h>
#define CCDER_MULTIBYTE_TAGS 1
#ifdef CCDER_MULTIBYTE_TAGS
typedef unsigned long ccder_tag;
#else
typedef uint8_t ccder_tag;
#endif
typedef struct ccder_blob {
uint8_t *cc_ended_by(der_end) der;
uint8_t *der_end;
} ccder_blob;
typedef struct ccder_read_blob {
const uint8_t *cc_ended_by(der_end) der;
const uint8_t *der_end;
} ccder_read_blob;
#define ccder_size(BEGIN, END) ((size_t)((END) - (BEGIN)))
#define ccder_blob_size(BLOB) ccder_size((BLOB).der, (BLOB).der_end)
// MARK: - ccder_blob_encode_ functions.
CC_NONNULL((1)) CC_NODISCARD
bool ccder_blob_encode_tag(ccder_blob *into, ccder_tag tag);
CC_NONNULL((1)) CC_NODISCARD
bool ccder_blob_encode_len(ccder_blob *into, size_t len);
CC_NONNULL((1)) CC_NODISCARD
bool ccder_blob_encode_tl(ccder_blob *into, ccder_tag tag, size_t len);
CC_NONNULL((1)) CC_NODISCARD
bool ccder_blob_encode_body(ccder_blob *into, size_t size, const uint8_t *cc_sized_by(size) body);
CC_NONNULL((1, 4)) CC_NODISCARD
bool ccder_blob_encode_body_tl(ccder_blob *into, ccder_tag tag, size_t size, const uint8_t *cc_sized_by(size) body);
CC_NONNULL((1, 3)) CC_NODISCARD
bool ccder_blob_reserve(ccder_blob *into, size_t reserve_size, ccder_blob *out_reserved);
CC_NONNULL((1, 4)) CC_NODISCARD
bool ccder_blob_reserve_tl(ccder_blob *into, ccder_tag tag, size_t reserve_size, ccder_blob *out_reserved);
CC_NONNULL((1, 2)) CC_NODISCARD
bool ccder_blob_encode_oid(ccder_blob *into, ccoid_t oid);
CC_NONNULL((1, 4)) CC_NODISCARD
bool ccder_blob_encode_implicit_integer(ccder_blob *into, ccder_tag implicit_tag, cc_size n, const cc_unit *cc_counted_by(n) s);
CC_NONNULL((1, 3)) CC_NODISCARD
bool ccder_blob_encode_integer(ccder_blob *into, cc_size n, const cc_unit *cc_counted_by(n) s);
CC_NONNULL((1)) CC_NODISCARD
bool ccder_blob_encode_implicit_uint64(ccder_blob *into, ccder_tag implicit_tag, uint64_t value);
CC_NONNULL((1)) CC_NODISCARD
bool ccder_blob_encode_uint64(ccder_blob *into, uint64_t value);
CC_NONNULL((1, 3)) CC_NODISCARD
bool ccder_blob_encode_octet_string(ccder_blob *into, cc_size n, const cc_unit *cc_counted_by(n) s);
CC_NONNULL((1, 4)) CC_NODISCARD
bool ccder_blob_encode_implicit_octet_string(ccder_blob *into, ccder_tag implicit_tag, cc_size n, const cc_unit *cc_counted_by(n) s);
CC_NONNULL((1, 4)) CC_NODISCARD
bool ccder_blob_encode_implicit_raw_octet_string(ccder_blob *into, ccder_tag implicit_tag, size_t s_size, const uint8_t *cc_sized_by(s_size) s);
CC_NONNULL((1, 3)) CC_NODISCARD
bool ccder_blob_encode_raw_octet_string(ccder_blob *into, size_t s_size, const uint8_t *cc_sized_by(s_size) s);
CC_NONNULL((1, 3)) CC_NODISCARD
bool ccder_blob_encode_eckey(ccder_blob *into, size_t priv_byte_size, const uint8_t *cc_sized_by(priv_byte_size) priv_key, ccoid_t oid, size_t pub_byte_size, const uint8_t *cc_sized_by(pub_byte_size) pub_key);
// MARK: - ccder_blob_decode_ functions.
CC_NONNULL((1, 2)) CC_NODISCARD
bool ccder_blob_decode_tag(ccder_read_blob *from, ccder_tag *tag);
CC_NONNULL((1, 2)) CC_NODISCARD
bool ccder_blob_decode_len(ccder_read_blob *from, size_t *size);
CC_NONNULL((1, 2)) CC_NODISCARD
bool ccder_blob_decode_len_strict(ccder_read_blob *from, size_t *size);
CC_NONNULL((1, 3)) CC_NODISCARD
bool ccder_blob_decode_tl(ccder_read_blob *from, ccder_tag expected_tag, size_t *size);
CC_NONNULL((1, 3)) CC_NODISCARD
bool ccder_blob_decode_tl_strict(ccder_read_blob *from, ccder_tag expected_tag, size_t *size);
CC_NONNULL((1, 3)) CC_NODISCARD
bool ccder_blob_decode_range(ccder_read_blob *from, ccder_tag expected_tag, ccder_read_blob *range_blob);
CC_NONNULL((1, 3)) CC_NODISCARD
bool ccder_blob_decode_range_strict(ccder_read_blob *from, ccder_tag expected_tag, ccder_read_blob *range_blob);
CC_NONNULL((1, 2)) CC_NODISCARD
bool ccder_blob_decode_sequence_tl(ccder_read_blob *from, ccder_read_blob *range_blob);
CC_NONNULL((1, 2)) CC_NODISCARD
bool ccder_blob_decode_sequence_tl_strict(ccder_read_blob *from, ccder_read_blob *range_blob);
CC_NONNULL((1, 2)) CC_NODISCARD
bool ccder_blob_decode_uint_n(ccder_read_blob *from, cc_size *n);
CC_NONNULL((1)) CC_NODISCARD
bool ccder_blob_decode_uint64(ccder_read_blob *from, uint64_t *r);
CC_NONNULL((1, 3)) CC_NODISCARD
bool ccder_blob_decode_uint(ccder_read_blob *from, cc_size n, cc_unit *cc_counted_by(n));
CC_NONNULL((1, 3)) CC_NODISCARD
bool ccder_blob_decode_uint_strict(ccder_read_blob *from, cc_size n, cc_unit *cc_counted_by(n));
CC_NONNULL((1, 3, 4)) CC_NODISCARD
bool ccder_blob_decode_seqii(ccder_read_blob *from, size_t n, cc_unit *cc_counted_by(n) r, cc_unit *cc_counted_by(n) s);
CC_NONNULL((1, 3, 4)) CC_NODISCARD
bool ccder_blob_decode_seqii_strict(ccder_read_blob *from, size_t n, cc_unit *cc_counted_by(n) r, cc_unit *cc_counted_by(n) s);
CC_NONNULL((1, 2)) CC_NODISCARD
bool ccder_blob_decode_oid(ccder_read_blob *from, ccoid_t *oidp);
CC_NONNULL((1, 2, 3)) CC_NODISCARD
bool ccder_blob_decode_bitstring(ccder_read_blob *from, ccder_read_blob *bit_string_range, size_t *bit_count);
CC_NONNULL((1, 2, 3, 4, 5, 6, 7)) CC_NODISCARD
bool ccder_blob_decode_eckey(ccder_read_blob *from, uint64_t *version, size_t *priv_key_byte_size, const uint8_t *cc_sized_by(*priv_key_byte_size) *priv_key, ccoid_t *oid, size_t *pub_key_byte_size, const uint8_t *cc_sized_by(*pub_key_byte_size) *pub_key, size_t *pub_key_bit_count);
#endif /* _CORECRYPTO_CCDER_BLOB_H_ */

View file

@ -0,0 +1,65 @@
/* Copyright (c) (2010,2012,2015,2016,2017,2018,2019) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCDES_H_
#define _CORECRYPTO_CCDES_H_
#include <corecrypto/ccmode.h>
#define CCDES_BLOCK_SIZE 8
#define CCDES_KEY_SIZE 8
extern const struct ccmode_ecb ccdes3_ltc_ecb_decrypt_mode;
extern const struct ccmode_ecb ccdes3_ltc_ecb_encrypt_mode;
const struct ccmode_ecb *ccdes_ecb_decrypt_mode(void);
const struct ccmode_ecb *ccdes_ecb_encrypt_mode(void);
const struct ccmode_cbc *ccdes_cbc_decrypt_mode(void);
const struct ccmode_cbc *ccdes_cbc_encrypt_mode(void);
const struct ccmode_cfb *ccdes_cfb_decrypt_mode(void);
const struct ccmode_cfb *ccdes_cfb_encrypt_mode(void);
const struct ccmode_cfb8 *ccdes_cfb8_decrypt_mode(void);
const struct ccmode_cfb8 *ccdes_cfb8_encrypt_mode(void);
const struct ccmode_ctr *ccdes_ctr_crypt_mode(void);
const struct ccmode_ofb *ccdes_ofb_crypt_mode(void);
const struct ccmode_ecb *ccdes3_ecb_decrypt_mode(void);
const struct ccmode_ecb *ccdes3_ecb_encrypt_mode(void);
const struct ccmode_cbc *ccdes3_cbc_decrypt_mode(void);
const struct ccmode_cbc *ccdes3_cbc_encrypt_mode(void);
const struct ccmode_cfb *ccdes3_cfb_decrypt_mode(void);
const struct ccmode_cfb *ccdes3_cfb_encrypt_mode(void);
const struct ccmode_cfb8 *ccdes3_cfb8_decrypt_mode(void);
const struct ccmode_cfb8 *ccdes3_cfb8_encrypt_mode(void);
const struct ccmode_ctr *ccdes3_ctr_crypt_mode(void);
const struct ccmode_ofb *ccdes3_ofb_crypt_mode(void);
int ccdes_key_is_weak( void *key, size_t length);
void ccdes_key_set_odd_parity(void *key, size_t length);
uint32_t
ccdes_cbc_cksum(const void *in, void *out, size_t length,
const void *key, size_t key_nbytes, const void *ivec);
#endif /* _CORECRYPTO_CCDES_H_ */

View file

@ -0,0 +1,116 @@
/* Copyright (c) (2010-2012,2014-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCDIGEST_H_
#define _CORECRYPTO_CCDIGEST_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccn.h>
/* To malloc a digest context for a given di, use malloc(ccdigest_di_size(di))
and assign the result to a pointer to a struct ccdigest_ctx. */
struct ccdigest_ctx {
uint8_t state[1];
} CC_ALIGNED(8);
typedef struct ccdigest_ctx *ccdigest_ctx_t;
struct ccdigest_state {
uint8_t state[1];
} CC_ALIGNED(8);
typedef struct ccdigest_state *ccdigest_state_t;
struct ccdigest_info {
size_t output_size;
size_t state_size;
size_t block_size;
size_t oid_size;
const unsigned char *oid;
const void *initial_state;
void(* CC_SPTR(ccdigest_info, compress))(ccdigest_state_t state, size_t nblocks,
const void *data);
void(* CC_SPTR(ccdigest_info, final))(const struct ccdigest_info *di, ccdigest_ctx_t ctx,
unsigned char *digest);
cc_impl_t impl;
};
/* Return sizeof a ccdigest_ctx for a given size_t _state_size_ and
size_t _block_size_. */
#define ccdigest_ctx_size(_state_size_, _block_size_) ((_state_size_) + sizeof(uint64_t) + (_block_size_) + sizeof(unsigned int))
/* Return sizeof a ccdigest_ctx for a given struct ccdigest_info *_di_. */
#define ccdigest_di_size(_di_) (ccdigest_ctx_size((_di_)->state_size, (_di_)->block_size))
/* Declare a ccdigest_ctx for a given size_t _state_size_ and
size_t _block_size_, named _name_. Can be used in structs or on the
stack. */
#define ccdigest_ctx_decl(_state_size_, _block_size_, _name_) cc_ctx_decl(struct ccdigest_ctx, ccdigest_ctx_size(_state_size_, _block_size_), _name_)
#define ccdigest_ctx_clear(_state_size_, _block_size_, _name_) cc_clear(ccdigest_ctx_size(_state_size_, _block_size_), _name_)
/* Declare a ccdigest_ctx for a given size_t _state_size_ and
size_t _block_size_, named _name_. Can be used on the stack. */
#define ccdigest_di_decl(_di_, _name_) cc_ctx_decl_vla(struct ccdigest_ctx, ccdigest_di_size(_di_), _name_)
#define ccdigest_di_clear(_di_, _name_) cc_clear(ccdigest_di_size(_di_), _name_)
/* Digest context field accessors. Consider the implementation private. */
#define ccdigest_state_u8(_di_, _ctx_) ccdigest_u8(ccdigest_state((_di_), (_ctx_)))
#define ccdigest_state_u32(_di_, _ctx_) ccdigest_u32(ccdigest_state((_di_), (_ctx_)))
#define ccdigest_state_u64(_di_, _ctx_) ccdigest_u64(ccdigest_state((_di_), (_ctx_)))
#define ccdigest_state_ccn(_di_, _ctx_) ccdigest_ccn(ccdigest_state((_di_), (_ctx_)))
#define ccdigest_nbits(_di_, _ctx_) (*((uint64_t *)((ccdigest_ctx_t)(_ctx_))->state))
#define ccdigest_state(_di_, _ctx_) ((ccdigest_state_t)(((ccdigest_ctx_t)(_ctx_))->state + sizeof(uint64_t)))
#define ccdigest_data(_di_, _ctx_) (((ccdigest_ctx_t)(_ctx_))->state + (_di_)->state_size + sizeof(uint64_t))
#define ccdigest_num(_di_, _ctx_) (*((unsigned int *)(((ccdigest_ctx_t)(_ctx_))->state + (_di_)->state_size + sizeof(uint64_t) + (_di_)->block_size)))
/* Digest state field accessors. Consider the implementation private. */
#define ccdigest_u8(_state_) ((uint8_t *)((ccdigest_state_t)(_state_)))
#define ccdigest_u32(_state_) ((uint32_t *)((ccdigest_state_t)(_state_)))
#define ccdigest_u64(_state_) ((uint64_t *)((ccdigest_state_t)(_state_)))
#define ccdigest_ccn(_state_) ((cc_unit *)((ccdigest_state_t)(_state_)))
void ccdigest_init(const struct ccdigest_info *di, ccdigest_ctx_t ctx);
void ccdigest_update(const struct ccdigest_info *di, ccdigest_ctx_t ctx,
size_t len, const void *data);
CC_INLINE
void ccdigest_final(const struct ccdigest_info *di, ccdigest_ctx_t ctx, unsigned char *digest)
{
di->final(di,ctx,digest);
}
void ccdigest(const struct ccdigest_info *di, size_t len,
const void *data, void *digest);
#define OID_DEF(_VALUE_) ((const unsigned char *)_VALUE_)
// https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration#Hash
#define CC_DIGEST_OID_MD2 OID_DEF("\x06\x08\x2A\x86\x48\x86\xF7\x0D\x02\x02")
#define CC_DIGEST_OID_MD4 OID_DEF("\x06\x08\x2A\x86\x48\x86\xF7\x0D\x02\x04")
#define CC_DIGEST_OID_MD5 OID_DEF("\x06\x08\x2A\x86\x48\x86\xF7\x0D\x02\x05")
#define CC_DIGEST_OID_SHA1 OID_DEF("\x06\x05\x2b\x0e\x03\x02\x1a")
#define CC_DIGEST_OID_SHA224 OID_DEF("\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04")
#define CC_DIGEST_OID_SHA256 OID_DEF("\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01")
#define CC_DIGEST_OID_SHA384 OID_DEF("\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02")
#define CC_DIGEST_OID_SHA512 OID_DEF("\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03")
#define CC_DIGEST_OID_SHA512_256 OID_DEF("\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06")
#define CC_DIGEST_OID_RMD160 OID_DEF("\x06\x05\x2B\x24\x03\x02\x01")
#define CC_DIGEST_OID_SHA3_224 OID_DEF("\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x07")
#define CC_DIGEST_OID_SHA3_256 OID_DEF("\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x08")
#define CC_DIGEST_OID_SHA3_384 OID_DEF("\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x09")
#define CC_DIGEST_OID_SHA3_512 OID_DEF("\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x0A")
// Provide current maximum sizes for block and state in order to prevent the
// need for dynamic allocation of context or many macro accessor functions.
#define MAX_DIGEST_BLOCK_SIZE 144 // Maximum block size is that of SHA3-224
#define MAX_DIGEST_STATE_SIZE 200 // SHA-3 state is 1600 bits
#define MAX_DIGEST_OUTPUT_SIZE 64
#endif /* _CORECRYPTO_CCDIGEST_H_ */

View file

@ -0,0 +1,26 @@
/* Copyright (c) (2010-2012,2015-2019,2021,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCDIGEST_PRIV_H_
#define _CORECRYPTO_CCDIGEST_PRIV_H_
#include <corecrypto/cc_priv.h>
#include <corecrypto/ccdigest.h>
#include <corecrypto/ccasn1.h>
#include <stdarg.h>
typedef const struct ccdigest_info *(ccdigest_lookup)(ccoid_t oid);
const struct ccdigest_info *ccdigest_oid_lookup(ccoid_t oid, ...);
#define ccdigest_copy_state(_di_, _dst_, _src_) cc_memcpy_nochk(_dst_, _src_, (_di_)->state_size)
#endif /* _CORECRYPTO_CCDIGEST_PRIV_H_ */

View file

@ -0,0 +1,111 @@
/* Copyright (c) (2010-2012,2014-2019,2021,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
/*!
@header corecrypto/ccdrbg.h
@abstract The functions provided in ccdrbg.h implement high-level accessors
to cryptographically secure random numbers.
*/
#ifndef _CORECRYPTO_CCDRBG_H_
#define _CORECRYPTO_CCDRBG_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccdrbg_impl.h>
#include <corecrypto/ccdrbg_df.h>
/*
* The maximum length of the entropy_input, additional_input (max_additional_input_length) , personalization string
* (max_personalization_string_length) and max_number_of_bits_per_request are implementation dependent
* but shall fit in a 32 bit register and be be less than or equal to the specified maximum length for the
* selected DRBG mechanism (NIST 800-90A Section 10).
*/
#define CCDRBG_MAX_ENTROPY_SIZE ((uint32_t)1<<16)
#define CCDRBG_MAX_ADDITIONALINPUT_SIZE ((uint32_t)1<<16)
#define CCDRBG_MAX_PSINPUT_SIZE ((uint32_t)1<<16)
#define CCDRBG_MAX_REQUEST_SIZE ((uint32_t)1<<16) //this is the absolute maximum in NIST 800-90A
#define CCDRBG_RESEED_INTERVAL ((uint64_t)1<<48) // must be able to fit the NIST maximum of 2^48
/*
* The entropyLength is forced to be greater or equal than the security strength.
* Nonce is not forced. It either needs to have 0.5*security strength entropy. Or, a vale that is repeated
* less than a 0.5*security strength bit random string.
* see below or NIST 800-90A for the definition of security strength
*/
int ccdrbg_init(const struct ccdrbg_info *info,
struct ccdrbg_state *drbg,
size_t entropyLength, const void* entropy,
size_t nonceLength, const void* nonce,
size_t psLength, const void* ps);
/*
* The entropyLength is forced to be greater or equal than the security strength.
*/
int ccdrbg_reseed(const struct ccdrbg_info *info,
struct ccdrbg_state *drbg,
size_t entropyLength, const void *entropy,
size_t additionalLength, const void *additional);
int ccdrbg_generate(const struct ccdrbg_info *info,
struct ccdrbg_state *drbg,
size_t dataOutLength, void *dataOut,
size_t additionalLength, const void *additional);
void ccdrbg_done(const struct ccdrbg_info *info,
struct ccdrbg_state *drbg);
size_t ccdrbg_context_size(const struct ccdrbg_info *info);
/*!
@function ccdrbg_must_reseed
@abstract Whether the DRBG requires a reseed to continue generation
@param info The DRBG implementation descriptor
@param drbg The DRBG state
@return true if the DRBG requires reseed; false otherwise
@discussion In strict FIPS mode, this returns true after a count of
requests exceeding the DRBG reseed interval of 2^48. When strict
FIPS mode is disabled, this function always returns false.
*/
bool ccdrbg_must_reseed(const struct ccdrbg_info *info,
const struct ccdrbg_state *drbg);
/*
* NIST SP 800-90 CTR_DRBG
* the maximum security strengh of drbg equals to the block size of the corresponding ECB.
*/
struct ccdrbg_nistctr_custom {
const struct ccmode_ctr *ctr_info;
size_t keylen;
int strictFIPS;
const ccdrbg_df_ctx_t *df_ctx;
};
void ccdrbg_factory_nistctr(struct ccdrbg_info *info, const struct ccdrbg_nistctr_custom *custom);
/*
* NIST SP 800-90 HMAC_DRBG
* the maximum security strengh of drbg is half of output size of the input hash function and it internally is limited to 256 bits
*/
struct ccdrbg_nisthmac_custom {
const struct ccdigest_info *di;
int strictFIPS;
};
void ccdrbg_factory_nisthmac(struct ccdrbg_info *info, const struct ccdrbg_nisthmac_custom *custom);
#endif /* _CORECRYPTO_CCDRBG_H_ */

View file

@ -0,0 +1,64 @@
/* Copyright (c) (2021,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCDRBG_DF_H_
#define _CORECRYPTO_CCDRBG_DF_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccmode_impl.h>
// This is an interface for derivation functions for DRBGs to convert
// high-entropy inputs into key material. Because this interface is
// intended for internal usage, we declare only the type names and
// initialization functions here.
typedef struct ccdrbg_df_ctx ccdrbg_df_ctx_t;
struct ccdrbg_df_ctx {
int (*derive_keys)(const ccdrbg_df_ctx_t *ctx,
size_t inputs_count,
const cc_iovec_t *inputs,
size_t keys_nbytes,
void *keys);
};
// This is a block-cipher-based instantiation of the derivation
// function for use in the CTR-DRBG.
typedef struct ccdrbg_df_bc_ctx ccdrbg_df_bc_ctx_t;
struct ccdrbg_df_bc_ctx {
ccdrbg_df_ctx_t df_ctx;
const struct ccmode_cbc *cbc_info;
size_t key_nbytes;
// See ccmode_impl.h.
cc_ctx_decl_field(cccbc_ctx, CCCBC_MAX_CTX_SIZE, cbc_ctx);
};
/*!
@function ccdrbg_df_bc_init
@abstract Initialize a block-cipher-based derivation function
@param ctx The derivation function context
@param cbc_info A descriptor for a CBC mode of a block cipher
@param key_nbytes The length of the key to use in the derivation function
@discussion Note that a fixed key is used internally, so only the
key length needs to be specified.
@return 0 if successful; negative otherwise
*/
CC_WARN_RESULT
CC_NONNULL_ALL
int ccdrbg_df_bc_init(ccdrbg_df_bc_ctx_t *ctx,
const struct ccmode_cbc *cbc_info,
size_t key_nbytes);
#endif /* _CORECRYPTO_CCDRBG_DF_H_ */

View file

@ -0,0 +1,78 @@
/* Copyright (c) (2012,2015,2016,2019-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCDRBG_IMPL_H_
#define _CORECRYPTO_CCDRBG_IMPL_H_
#include <corecrypto/cc.h>
/* opaque drbg structure */
struct ccdrbg_state;
struct ccdrbg_info {
/*! Size of the DRBG state in bytes **/
size_t size;
/*! Instantiate the DRBG
@param drbg The DRBG state
@param entropylen Length of entropy
@param entropy Entropy bytes
@param inlen Length of additional input
@param in Additional input bytes
@return 0 if successful
*/
int (*CC_SPTR(ccdrbg_info, init))(const struct ccdrbg_info *info, struct ccdrbg_state *drbg,
size_t entropyLength, const void* entropy,
size_t nonceLength, const void* nonce,
size_t psLength, const void* ps);
/*! Add entropy to the DRBG
@param drbg The DRBG state
@param entropylen Length of entropy
@param entropy Entropy bytes
@param inlen Length of additional input
@param in Additional input bytes
@return 0 if successful
*/
int (*CC_SPTR(ccdrbg_info, reseed))(struct ccdrbg_state *drbg,
size_t entropylen, const void *entropy,
size_t inlen, const void *in);
/*! Read from the DRBG in a FIPS Testing compliant manor
@param drbg The DRBG state to read from
@param out [out] Where to store the data
@param outlen Length of data desired (octets)
@param inlen Length of additional input
@param in Additional input bytes
@return 0 if successfull
*/
int (*CC_SPTR(ccdrbg_info, generate))(struct ccdrbg_state *drbg,
size_t outlen, void *out,
size_t inlen, const void *in);
/*! Terminate a DRBG state
@param drbg The DRBG state to terminate
*/
void (*CC_SPTR(ccdrbg_info, done))(struct ccdrbg_state *drbg);
/** private parameters */
const void *custom;
/*! Whether the DRBG requires a reseed to continue generation
@param drbg The DRBG state
@return true if the DRBG requires reseed; false otherwise
*/
bool (*CC_SPTR(ccdrbg_info, must_reseed))(const struct ccdrbg_state *drbg);
};
#endif // _CORECRYPTO_CCDRBG_IMPL_H_

View file

@ -0,0 +1,149 @@
/* Copyright (c) (2021) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCENTROPY_H_
#define _CORECRYPTO_CCENTROPY_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccdigest.h>
// An interface to provide high-entropy seeds to RNGs.
typedef struct ccentropy_ctx ccentropy_ctx_t;
typedef int (*ccentropy_get_seed_fn_t)(ccentropy_ctx_t *ctx,
size_t seed_nbytes,
void *seed);
typedef int (*ccentropy_add_entropy_fn_t)(ccentropy_ctx_t *ctx,
uint32_t entropy_nsamples,
size_t entropy_nbytes,
const void *entropy);
// A descriptor for an entropy implementation.
typedef struct ccentropy_info {
// This is a required function. Implementations should populate
// the seed with a full-entropy output. If they are temporarily
// unable due to insufficient entropy, they should return
// CCERR_OUT_OF_ENTROPY. If they are permanently unable they
// should return some other error (or abort).
ccentropy_get_seed_fn_t get_seed;
// This is an optional function. The caller will provide a set of
// (potentially low-quality) entropy samples, and the
// implementation should mix these into its internal
// state. Implementations are free to omit this function if it
// does not make sense (e.g. see ccentropy_rng below).
ccentropy_add_entropy_fn_t add_entropy;
} ccentropy_info_t;
// Common state for entropy implementations.
struct ccentropy_ctx {
// A pointer to the descriptor.
const ccentropy_info_t *info;
};
/*!
@function ccentropy_get_seed
@abstract Get a high-entropy seed.
@param ctx The entropy context.
@param seed_nbytes The size of the seed requested.
@param seed A buffer to receive the seed.
@return CCERR_OK on success; CCERR_OUT_OF_ENTROPY if entropy is
temporarily unavailable; some implementation-defined error (or
abort) otherwise.
*/
int ccentropy_get_seed(ccentropy_ctx_t *ctx,
size_t seed_nbytes,
void *seed);
/*!
@function ccentropy_add_entropy
@abstract Add fresh entropy samples to the context.
@param ctx The entropy context.
@param entropy_nsamples The count of samples included in this batch.
@param entropy_nbytes The size of the entropy payload in bytes.
@param entropy A buffer containing the fresh entropy samples.
@return CCERR_OK on success; CCERR_NOT_SUPPORTED if this operation
is not supported for the implementation; some implementation-defined
error (or abort) otherwise.
@discussion This operation is optional and will not be supported by
all implementations.
*/
int ccentropy_add_entropy(ccentropy_ctx_t *ctx,
uint32_t entropy_nsamples,
size_t entropy_nbytes,
const void *entropy);
// A simple wrapper around a ccrng instance. This implementation does
// not support the add_entropy interface.
typedef struct ccentropy_rng_ctx {
ccentropy_ctx_t entropy_ctx;
struct ccrng_state *rng_ctx;
size_t seed_max_nbytes;
} ccentropy_rng_ctx_t;
/*!
@function ccentropy_rng_init
@abstract Wrap a ccrng instance in the ccentropy interface.
@param ctx The entropy context.
@param rng_ctx The RNG to wrap.
@param seed_max_nbytes The maximum seed size that this RNG can provide.
@return CCERR_OK on success.
@discussion seed_max_nbytes should correspond to the security level
of the underlying RNG.
*/
int ccentropy_rng_init(ccentropy_rng_ctx_t *ctx,
struct ccrng_state *rng_ctx,
size_t seed_max_nbytes);
// An entropy conditioner based on digest functions. We assume a fixed
// per-sample entropy estimate measured in millibits
// (i.e. mbits). This estimate should be determined via offline
// analysis.
typedef struct ccentropy_digest_ctx {
ccentropy_ctx_t entropy_ctx;
const struct ccdigest_info *digest_info;
ccdigest_ctx_decl(MAX_DIGEST_STATE_SIZE,
MAX_DIGEST_BLOCK_SIZE,
digest_ctx);
uint32_t entropy_mbits_per_sample;
uint32_t entropy_mbits;
} ccentropy_digest_ctx_t;
#define CCENTROPY_MBITS_PER_BYTE ((uint32_t)(8000))
/*!
@function ccentropy_digest_init
@abstract Initialize a digest-based entropy conditioner.
@param ctx The entropy context.
@param digest_info A descriptor for the digest.
@param entropy_mbits_per_sample An estimate of per-sample entropy measured in millibits.
@return CCERR_OK on success.
@discussion The estimated entropy per sample should be determined
via offline analysis.
*/
int ccentropy_digest_init(struct ccentropy_digest_ctx *ctx,
const struct ccdigest_info *digest_info,
uint32_t entropy_mbits_per_sample);
#endif /* _CORECRYPTO_CCENTROPY_H_ */

View file

@ -0,0 +1,67 @@
/* Copyright (c) (2010-2012,2014-2021) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCHMAC_H_
#define _CORECRYPTO_CCHMAC_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccdigest.h>
/* An hmac_ctx_t is normally allocated as an array of these. */
struct cchmac_ctx {
uint8_t b[1];
} CC_ALIGNED(8);
typedef struct cchmac_ctx* cchmac_ctx_t;
#define cchmac_ctx_size(STATE_SIZE, BLOCK_SIZE) (cc_pad_align(ccdigest_ctx_size(STATE_SIZE, BLOCK_SIZE)) + (STATE_SIZE))
#define cchmac_di_size(_di_) (cchmac_ctx_size((_di_)->state_size, (_di_)->block_size))
#define cchmac_ctx_n(STATE_SIZE, BLOCK_SIZE) ccn_nof_size(cchmac_ctx_size((STATE_SIZE), (BLOCK_SIZE)))
#define cchmac_ctx_decl(STATE_SIZE, BLOCK_SIZE, _name_) cc_ctx_decl_vla(struct cchmac_ctx, cchmac_ctx_size(STATE_SIZE, BLOCK_SIZE), _name_)
#define cchmac_ctx_clear(STATE_SIZE, BLOCK_SIZE, _name_) cc_clear(cchmac_ctx_size(STATE_SIZE, BLOCK_SIZE), _name_)
#define cchmac_di_decl(_di_, _name_) cchmac_ctx_decl((_di_)->state_size, (_di_)->block_size, _name_)
#define cchmac_di_clear(_di_, _name_) cchmac_ctx_clear((_di_)->state_size, (_di_)->block_size, _name_)
/* Return a ccdigest_ctx_t which can be accesed with the macros in ccdigest.h */
#define cchmac_digest_ctx(_di_, HC) ((ccdigest_ctx_t)(HC))
/* Accesors for ostate fields, this is all cchmac_ctx_t adds to the ccdigest_ctx_t. */
#define cchmac_ostate(_di_, HC) ((ccdigest_state_t)(((cchmac_ctx_t)(HC))->b + cc_pad_align(ccdigest_di_size(_di_))))
#define cchmac_ostate8(_di_, HC) (ccdigest_u8(cchmac_ostate(_di_, HC)))
#define cchmac_ostate32(_di_, HC) (ccdigest_u32(cchmac_ostate(_di_, HC)))
#define cchmac_ostate64(_di_, HC) (ccdigest_u64(cchmac_ostate(_di_, HC)))
#define cchmac_ostateccn(_di_, HC) (ccdigest_ccn(cchmac_ostate(_di_, HC)))
/* Convenience accessors for ccdigest_ctx_t fields. */
#define cchmac_istate(_di_, HC) ccdigest_state(_di_, ((ccdigest_ctx_t)(HC)))
#define cchmac_istate8(_di_, HC) ccdigest_u8(cchmac_istate(_di_, HC))
#define cchmac_istate32(_di_, HC) ccdigest_u32(cchmac_istate(_di_, HC))
#define cchmac_istate64(_di_, HC) ccdigest_u64(cchmac_istate(_di_, HC))
#define cchmac_istateccn(_di_, HC) ccdigest_ccn(cchmac_istate(_di_, HC))
#define cchmac_data(_di_, HC) ccdigest_data(_di_, ((ccdigest_ctx_t)(HC)))
#define cchmac_num(_di_, HC) ccdigest_num(_di_, ((ccdigest_ctx_t)(HC)))
#define cchmac_nbits(_di_, HC) ccdigest_nbits(_di_, ((ccdigest_ctx_t)(HC)))
void cchmac_init(const struct ccdigest_info *di, cchmac_ctx_t ctx,
size_t key_len, const void *key);
void cchmac_update(const struct ccdigest_info *di, cchmac_ctx_t ctx,
size_t data_len, const void *data);
void cchmac_final(const struct ccdigest_info *di, cchmac_ctx_t ctx,
unsigned char *mac);
void cchmac(const struct ccdigest_info *di, size_t key_len,
const void *key, size_t data_len, const void *data,
unsigned char *mac);
#endif /* _CORECRYPTO_CCHMAC_H_ */

View file

@ -0,0 +1,234 @@
/* Copyright (c) (2018-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCKPRNG_H_
#define _CORECRYPTO_CCKPRNG_H_
#include <corecrypto/cc.h>
#include "ccrng_fortuna.h"
#include "ccrng_crypto.h"
#include <corecrypto/ccrng_schedule.h>
#include <corecrypto/ccentropy.h>
#include <corecrypto/ccdrbg.h>
#include "cc_lock.h"
// This is a Fortuna-inspired PRNG. While it differs from Fortuna in
// many minor details, the biggest difference is its support for
// multiple independent output generators. This is to make it suitable
// for use in concurrent environments.
//
// This PRNG targets a 256-bit security level.
//
// First, the user should call cckprng_init. The user must specify the
// maximum number of output generators that might be
// needed. (Typically, users should align this argument with the
// number of available CPUs.)
//
// The user must also provide a read-only handle to an entropy
// source. This is a fixed-size buffer that will receive entropy
// updates out of band from the PRNG (e.g. in an interrupt
// handler). The PRNG will consume entropy from this buffer according
// to an internal schedule driven by calls to cckprng_refresh (see
// below).
//
// The user should call cckprng_initgen for as many output generators
// as are needed. The numeric argument is an identifier to be reused
// during calls to cckprng_generate (see below) and must be less than
// the maximum number of generators specified to cckprng_init.
//
// After initialization, the user is free to call cckprng_generate to
// generate random bytes. The user must specify the generator in this
// call using a numeric identifier passed in the call to
// cckprng_initgen.
//
// Output generation is limited to 256 bytes per request. Users should
// make multiple requests if more output is needed.
//
// The user is expected to call cckprng_refresh regularly. This
// function consumes entropy and mixes it into the output generators
// according to an internal schedule.
//
// This implementation is thread-safe. Internally, a set of mutexes
// guard access to internal state. Most functions rely on a single
// mutex to protect shared state. The main exception is the
// cckprng_generate function, which uses a per-generator mutex to
// allow concurrent output generation on different threads.
//
// Another important exception is cckprng_refresh. While this function
// relies on the shared mutex, it returns immediately if it cannot
// acquire it.
//
// The PRNG also supports user-initiated reseeds. This is to support a
// user-writable random device.
//
// This PRNG supports reseeds concurrent with output generation,
// i.e. it is safe to call cckprng_reseed or cckprng_refresh while
// another thread is calling cckprng_generate.
#define CCKPRNG_SEED_NBYTES 32
// A function pointer to fill an entropy buffer. It should return some
// estimate of entropy (e.g. the number of timing samples resident in
// the buffer). The implementation may return zero if no entropy is
// available. The implementation should return negative in case of an
// error (e.g. a failure in continuous health tests).
//
// The caller should set entropy_nbytes to the maximum size of the
// input buffer, and the implementation should set it to the number of
// bytes it has initialized. The third argument is arbitrary state the
// implementation provides and receives back on each call.
typedef ccrng_fortuna_getentropy cckprng_getentropy;
#define CCKPRNG_ENTROPY_SIZE 64
#define CCKPRNG_DRBG_STATE_MAX_SIZE ((size_t)1280)
#define CCKPRNG_CACHED_BUF_SIZE ((size_t)256)
#define CCKPRNG_MAX_REQUEST_SIZE ((size_t)4096)
struct cckprng_ctx {
// A flag set every time Fortuna reseeds itself
ccrng_schedule_atomic_flag_ctx_t schedule_ctx;
ccentropy_rng_ctx_t entropy_ctx;
cc_lock_ctx_t lock_ctx;
struct ccdrbg_info drbg_info;
uint8_t drbg_state[CCKPRNG_DRBG_STATE_MAX_SIZE];
ccdrbg_df_bc_ctx_t drbg_df_ctx;
uint8_t cache[CCKPRNG_CACHED_BUF_SIZE];
ccrng_crypto_ctx_t rng_ctx;
struct ccrng_fortuna_ctx fortuna_ctx;
};
// This collection of function pointers is just a convenience for
// registering the PRNG with xnu
struct cckprng_funcs {
void (*CC_SPTR(cckprng_funcs, init))(struct cckprng_ctx *ctx,
size_t seed_nbytes,
const void *seed,
size_t nonce_nbytes,
const void *nonce,
cckprng_getentropy getentropy,
void *getentropy_arg);
void (*CC_SPTR(cckprng_funcs, initgen))(struct cckprng_ctx *ctx, unsigned gen_idx);
void (*CC_SPTR(cckprng_funcs, reseed))(struct cckprng_ctx *ctx, size_t nbytes, const void *seed);
void (*CC_SPTR(cckprng_funcs, refresh))(struct cckprng_ctx *ctx);
void (*CC_SPTR(cckprng_funcs, generate))(struct cckprng_ctx *ctx, unsigned gen_idx, size_t nbytes, void *out);
void (*CC_SPTR(cckprng_funcs, init_with_getentropy))(struct cckprng_ctx *ctx,
unsigned max_ngens,
size_t seed_nbytes,
const void *seed,
size_t nonce_nbytes,
const void *nonce,
cckprng_getentropy getentropy,
void *getentropy_arg);
};
/*
@function cckprng_init
@abstract Initialize a kernel PRNG context.
@param ctx Context for this instance
@param seed_nbytes Length of the seed in bytes
@param seed Pointer to a high-entropy seed
@param nonce_nbytes Length of the nonce in bytes
@param nonce Pointer to a single-use nonce
@param getentropy A function pointer to fill an entropy buffer
@param getentropy_arg State provided to the entropy function
@discussion See the @p cckprng_getentropy type definition for discussion on its semantics.
*/
void cckprng_init(struct cckprng_ctx *ctx,
size_t seed_nbytes,
const void *seed,
size_t nonce_nbytes,
const void *nonce,
cckprng_getentropy getentropy,
void *getentropy_arg);
/*
@function cckprng_init_with_getentropy
@abstract Initialize a kernel PRNG context.
@param ctx Context for this instance
@param max_ngens Maximum count of generators that may be allocated
@param seed_nbytes Length of the seed in bytes
@param seed Pointer to a high-entropy seed
@param nonce_nbytes Length of the nonce in bytes
@param nonce Pointer to a single-use nonce
@param getentropy A function pointer to fill an entropy buffer
@param getentropy_arg State provided to the entropy function
@discussion @p max_ngens should be set based on an upper bound of CPUs available on the device. See the @p cckprng_getentropy type definition for discussion on its semantics.
*/
void cckprng_init_with_getentropy(struct cckprng_ctx *ctx,
unsigned max_ngens,
size_t seed_nbytes,
const void *seed,
size_t nonce_nbytes,
const void *nonce,
cckprng_getentropy getentropy,
void *getentropy_arg);
/*
@function cckprng_initgen
@abstract Initialize an output generator.
@param ctx Context for this instance
@param gen_idx Index of the generator
@discussion @p gen_idx must be less than @p max_ngens provided to @cckprng_init and must be unique within the lifetime of a PRNG context. This function will abort if these contracts are violated.
*/
void cckprng_initgen(struct cckprng_ctx *ctx, unsigned gen_idx);
/*
@function cckprng_reseed
@abstract Reseed a kernel PRNG context with a user-supplied seed.
@param ctx Context for this instance
@param nbytes Length of the seed in bytes
@param seed Pointer to a high-entropy seed
@discussion It is safe to expose this function to attacker-controlled requests (e.g. writes to /dev/random).
*/
void cckprng_reseed(struct cckprng_ctx *ctx, size_t nbytes, const void *seed);
/*
@function cckprng_refresh
@abstract Consume entropy and reseed according to an internal schedule.
@param ctx Context for this instance
@discussion This function should be called on a regular basis. (For example, it is reasonable to call this inline before a call to @p cckprng_generate.) This function will not necessarily consume entropy or reseed the internal state on any given invocation. To force an immediate reseed, call @p cckprng_reseed.
*/
void cckprng_refresh(struct cckprng_ctx *ctx);
#define CCKPRNG_GENERATE_MAX_NBYTES 256
/*
@function cckprng_generate
@abstract Generate random values for use in applications.
@param ctx Context for this instance
@param gen_idx Index of the output generator
@param nbytes Length of the desired output in bytes
@param out Pointer to the output buffer
@discussion @p gen_idx must be a previous argument to @p cckprng_initgen. @p nbytes must be less than or equal to @p CCKPRNG_GENERATE_MAX_NBYTES. (Callers may invoke this function in a loop to generate larger outputs.) This function will abort if these contracts are violated.
*/
void cckprng_generate(struct cckprng_ctx *ctx, unsigned gen_idx, size_t nbytes, void *out);
#endif /* _CORECRYPTO_CCKPRNG_H_ */

View file

@ -0,0 +1,26 @@
/* Copyright (c) (2010,2015,2017,2018,2019) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCMD4_H_
#define _CORECRYPTO_CCMD4_H_
#include <corecrypto/ccdigest.h>
#define CCMD4_BLOCK_SIZE 64
#define CCMD4_OUTPUT_SIZE 16
#define CCMD4_STATE_SIZE 16
extern const struct ccdigest_info ccmd4_ltc_di;
/* default is libtomcrypt */
#define ccmd4_di ccmd4_ltc_di
#endif /* _CORECRYPTO_CCMD4_H_ */

View file

@ -0,0 +1,859 @@
/* Copyright (c) (2010-2012,2014-2023) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCMODE_H_
#define _CORECRYPTO_CCMODE_H_
#include <corecrypto/cc_config.h>
#include <corecrypto/cc_priv.h>
#include <corecrypto/ccmode_impl.h>
#include <corecrypto/ccmode_siv.h>
#include <corecrypto/ccmode_siv_hmac.h>
CC_PTRCHECK_CAPABLE_HEADER()
/* ECB mode. */
/* Declare a ecb key named _name_. Pass the size field of a struct ccmode_ecb
for _size_. */
#define ccecb_ctx_decl(_size_, _name_) cc_ctx_decl_vla(ccecb_ctx, _size_, _name_)
#define ccecb_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
size_t ccecb_context_size(const struct ccmode_ecb *mode);
size_t ccecb_block_size(const struct ccmode_ecb *mode);
int ccecb_init(const struct ccmode_ecb *mode, ccecb_ctx *ctx, size_t key_len, const void *cc_sized_by(key_len) key);
int ccecb_update(const struct ccmode_ecb *mode, const ccecb_ctx *ctx, size_t nblocks, const void *cc_indexable in, void *cc_indexable out);
cc_ptrcheck_unavailable_r(ccecb_one_shot_explicit)
int ccecb_one_shot(const struct ccmode_ecb *mode,
size_t key_len,
const void *cc_sized_by(key_len) key,
size_t nblocks,
const void *cc_unsafe_indexable in,
void *cc_unsafe_indexable out);
int ccecb_one_shot_explicit(const struct ccmode_ecb *mode,
size_t key_len,
size_t block_size,
size_t nblocks,
const void *cc_sized_by(key_len) key,
const void *cc_sized_by(block_size * nblocks) in,
void *cc_sized_by(block_size * nblocks) out);
/* CBC mode. */
/* Declare a cbc key named _name_. Pass the size field of a struct ccmode_cbc
for _size_. */
#define cccbc_ctx_decl(_size_, _name_) cc_ctx_decl_vla(cccbc_ctx, _size_, _name_)
#define cccbc_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
/* Declare a cbc iv tweak named _name_. Pass the blocksize field of a
struct ccmode_cbc for _size_. */
#define cccbc_iv_decl(_size_, _name_) cc_ctx_decl_vla(cccbc_iv, _size_, _name_)
#define cccbc_iv_clear(_size_, _name_) cc_clear(_size_, _name_)
/* Actual symmetric algorithm implementation can provide you one of these.
Alternatively you can create a ccmode_cbc instance from any ccmode_ecb
cipher. To do so, statically initialize a struct ccmode_cbc using the
CCMODE_FACTORY_CBC_DECRYPT or CCMODE_FACTORY_CBC_ENCRYPT macros.
Alternatively you can dynamically initialize a struct ccmode_cbc
ccmode_factory_cbc_decrypt() or ccmode_factory_cbc_encrypt(). */
size_t cccbc_context_size(const struct ccmode_cbc *mode);
size_t cccbc_block_size(const struct ccmode_cbc *mode);
int cccbc_init(const struct ccmode_cbc *mode, cccbc_ctx *ctx, size_t key_len, const void *cc_sized_by(key_len) key);
int cccbc_copy_iv(cccbc_iv *cc_sized_by(len) iv_ctx, const void *cc_sized_by(len) iv, size_t len);
int cccbc_clear_iv(cccbc_iv *cc_sized_by(len) iv_ctx, size_t len);
cc_ptrcheck_unavailable() // Use cccbc_copy_iv() or cccbc_clear_iv() directly.
int cccbc_set_iv(const struct ccmode_cbc *mode, cccbc_iv *iv_ctx, const void *iv);
int cccbc_update(const struct ccmode_cbc *mode, const cccbc_ctx *ctx, cccbc_iv *iv, size_t nblocks, const void *cc_indexable in, void *cc_indexable out);
cc_ptrcheck_unavailable_r(cccbc_one_shot_explicit)
int cccbc_one_shot(const struct ccmode_cbc *mode,
size_t key_len,
const void *cc_sized_by(key_len) key,
const void *iv,
size_t nblocks,
const void *cc_unsafe_indexable in,
void *cc_unsafe_indexable out);
int cccbc_one_shot_explicit(const struct ccmode_cbc *mode,
size_t key_len,
size_t iv_len,
size_t block_size,
size_t nblocks,
const void *cc_sized_by(key_len) key,
const void *cc_sized_by(iv_len) iv,
const void *cc_sized_by(block_size * nblocks) in,
void *cc_sized_by(block_size * nblocks) out);
/* CFB mode. */
/* Declare a cfb key named _name_. Pass the size field of a struct ccmode_cfb
for _size_. */
#define cccfb_ctx_decl(_size_, _name_) cc_ctx_decl_vla(cccfb_ctx, _size_, _name_)
#define cccfb_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
size_t cccfb_context_size(const struct ccmode_cfb *mode);
size_t cccfb_block_size(const struct ccmode_cfb *mode);
int cccfb_init(const struct ccmode_cfb *mode, cccfb_ctx *ctx, size_t key_len, const void *cc_sized_by(key_len) key, const void *cc_indexable iv);
int cccfb_update(const struct ccmode_cfb *mode, cccfb_ctx *ctx, size_t nbytes, const void *cc_sized_by(nbytes) in, void *cc_sized_by(nbytes) out);
int cccfb_one_shot(const struct ccmode_cfb *mode,
size_t key_len,
const void *cc_sized_by(key_len) key,
const void *cc_indexable iv,
size_t nbytes,
const void *cc_sized_by(nbytes) in,
void *cc_sized_by(nbytes) out);
/* CFB8 mode. */
/* Declare a cfb8 key named _name_. Pass the size field of a struct ccmode_cfb8
for _size_. */
#define cccfb8_ctx_decl(_size_, _name_) cc_ctx_decl_vla(cccfb8_ctx, _size_, _name_)
#define cccfb8_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
size_t cccfb8_context_size(const struct ccmode_cfb8 *mode);
size_t cccfb8_block_size(const struct ccmode_cfb8 *mode);
int cccfb8_init(const struct ccmode_cfb8 *mode, cccfb8_ctx *ctx, size_t key_len, const void *cc_sized_by(key_len) key, const void *cc_indexable iv);
int cccfb8_update(const struct ccmode_cfb8 *mode, cccfb8_ctx *ctx, size_t nbytes, const void *cc_sized_by(nbytes) in, void *cc_sized_by(nbytes) out);
int cccfb8_one_shot(const struct ccmode_cfb8 *mode,
size_t key_len,
const void *cc_sized_by(key_len) key,
const void *cc_indexable iv,
size_t nbytes,
const void *cc_sized_by(nbytes) in,
void *cc_sized_by(nbytes) out);
/* CTR mode. */
/* Declare a ctr key named _name_. Pass the size field of a struct ccmode_ctr
for _size_. */
#define ccctr_ctx_decl(_size_, _name_) cc_ctx_decl_vla(ccctr_ctx, _size_, _name_)
#define ccctr_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
/* This is Integer Counter Mode: The IV is the initial value of the counter
that is incremented by 1 for each new block. Use the mode flags to select
if the IV/Counter is stored in big or little endian. */
size_t ccctr_context_size(const struct ccmode_ctr *mode);
size_t ccctr_block_size(const struct ccmode_ctr *mode);
int ccctr_init(const struct ccmode_ctr *mode, ccctr_ctx *ctx, size_t key_len, const void *cc_sized_by(key_len) key, const void *cc_indexable iv);
int ccctr_update(const struct ccmode_ctr *mode, ccctr_ctx *ctx, size_t nbytes, const void *cc_sized_by(nbytes) in, void *cc_sized_by(nbytes) out);
int ccctr_one_shot(const struct ccmode_ctr *mode,
size_t key_len,
const void *cc_sized_by(key_len) key,
const void *cc_indexable iv,
size_t nbytes,
const void *cc_sized_by(nbytes) in,
void *cc_sized_by(nbytes) out);
/* OFB mode. */
/* Declare a ofb key named _name_. Pass the size field of a struct ccmode_ofb
for _size_. */
#define ccofb_ctx_decl(_size_, _name_) cc_ctx_decl_vla(ccofb_ctx, _size_, _name_)
#define ccofb_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
size_t ccofb_context_size(const struct ccmode_ofb *mode);
size_t ccofb_block_size(const struct ccmode_ofb *mode);
int ccofb_init(const struct ccmode_ofb *mode, ccofb_ctx *ctx, size_t key_len, const void *cc_sized_by(key_len) key, const void *cc_indexable iv);
int ccofb_update(const struct ccmode_ofb *mode, ccofb_ctx *ctx, size_t nbytes, const void *cc_sized_by(nbytes) in, void *cc_sized_by(nbytes) out);
int ccofb_one_shot(const struct ccmode_ofb *mode,
size_t key_len,
const void *cc_sized_by(key_len) key,
const void *cc_indexable iv,
size_t nbytes,
const void *cc_sized_by(nbytes) in,
void *cc_sized_by(nbytes) out);
/* XTS mode. */
/* Declare a xts key named _name_. Pass the size field of a struct ccmode_xts
for _size_. */
#define ccxts_ctx_decl(_size_, _name_) cc_ctx_decl_vla(ccxts_ctx, _size_, _name_)
#define ccxts_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
/* Declare a xts tweak named _name_. Pass the tweak_size field of a
struct ccmode_xts for _size_. */
#define ccxts_tweak_decl(_size_, _name_) cc_ctx_decl_vla(ccxts_tweak, _size_, _name_)
#define ccxts_tweak_clear(_size_, _name_) cc_clear(_size_, _name_)
/* Actual symmetric algorithm implementation can provide you one of these.
Alternatively you can create a ccmode_xts instance from any ccmode_ecb
cipher. To do so, statically initialize a struct ccmode_xts using the
CCMODE_FACTORY_XTS_DECRYPT or CCMODE_FACTORY_XTS_ENCRYPT macros. Alternatively
you can dynamically initialize a struct ccmode_xts
ccmode_factory_xts_decrypt() or ccmode_factory_xts_encrypt(). */
/* NOTE that xts mode does not do cts padding. It's really an xex mode.
If you need cts padding use the ccpad_xts_encrypt and ccpad_xts_decrypt
functions. Also note that xts only works for ecb modes with a block_size
of 16. */
size_t ccxts_context_size(const struct ccmode_xts *mode);
size_t ccxts_block_size(const struct ccmode_xts *mode);
/*!
@function ccxts_init
@abstract Initialize an XTS context.
@param mode Descriptor for the mode
@param ctx Context for this instance
@param key_nbytes Length of the key arguments in bytes
@param data_key Key for data encryption
@param tweak_key Key for tweak generation
@result 0 iff successful.
@discussion For security reasons, the two keys must be different.
*/
int ccxts_init(const struct ccmode_xts *mode, ccxts_ctx *ctx, size_t key_nbytes, const void *cc_sized_by(key_nbytes) data_key, const void *cc_sized_by(key_nbytes) tweak_key);
/*!
@function ccxts_set_tweak
@abstract Initialize the tweak for a sector.
@param mode Descriptor for the mode
@param ctx Context for this instance
@param tweak Context for the tweak for this sector
@param iv Data used to generate the tweak
@discussion The IV must be exactly one block in length.
*/
int ccxts_set_tweak(const struct ccmode_xts *mode, ccxts_ctx *ctx, ccxts_tweak *tweak, const void *cc_indexable iv);
/*!
@function ccxts_update
@abstract Encrypt or decrypt data.
@param mode Descriptor for the mode
@param ctx Context for an instance
@param tweak Context for the tweak for this sector
@param nblocks Length of the data in blocks
@param in Input data
@param out Output buffer
@result The updated internal buffer of the tweak context. May be ignored.
*/
void *cc_unsafe_indexable
ccxts_update(const struct ccmode_xts *mode, ccxts_ctx *ctx, ccxts_tweak *tweak, size_t nblocks, const void *cc_indexable in, void *cc_indexable out);
/*!
@function ccxts_one_shot
@abstract Encrypt or decrypt data in XTS mode.
@param mode Descriptor for the mode
@param key_nbytes Length of the key arguments in bytes
@param data_key Key for data encryption
@param tweak_key Key for tweak generation
@param iv Data used to generate the tweak
@param nblocks Length of the data in blocks
@param in Input data
@param out Output buffer
@result 0 iff successful.
@discussion For security reasons, the two keys must be different.
*/
int ccxts_one_shot(const struct ccmode_xts *mode,
size_t key_nbytes,
const void *cc_sized_by(key_nbytes) data_key,
const void *cc_sized_by(key_nbytes) tweak_key,
const void *cc_unsafe_indexable iv,
size_t nblocks,
const void *cc_unsafe_indexable in,
void *cc_unsafe_indexable out);
/* Authenticated cipher modes. */
/* GCM mode. */
/* Declare a gcm key named _name_. Pass the size field of a struct ccmode_gcm
for _size_. */
#define ccgcm_ctx_decl(_size_, _name_) cc_ctx_decl_vla(ccgcm_ctx, _size_, _name_)
#define ccgcm_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
#define CCGCM_IV_NBYTES 12
#define CCGCM_BLOCK_NBYTES 16
/* (2^32 - 2) blocks */
/* (2^36 - 32) bytes */
/* (2^39 - 256) bits */
/* Exceeding this figure breaks confidentiality and authenticity. */
#define CCGCM_TEXT_MAX_NBYTES ((1ULL << 36) - 32ULL)
size_t ccgcm_context_size(const struct ccmode_gcm *mode);
size_t ccgcm_block_size(const struct ccmode_gcm *mode);
/*!
@function ccgcm_init
@abstract Initialize a GCM context.
@param mode Descriptor for the mode
@param ctx Context for this instance
@param key_nbytes Length of the key in bytes
@param key Key for the underlying blockcipher (AES)
@result 0 iff successful.
@discussion The correct sequence of calls is:
@code ccgcm_init(...)
ccgcm_set_iv(...)
ccgcm_aad(...) (may be called zero or more times)
ccgcm_update(...) (may be called zero or more times)
ccgcm_finalize(...)
To reuse the context for additional encryptions, follow this sequence:
@code ccgcm_reset(...)
ccgcm_set_iv(...)
ccgcm_aad(...) (may be called zero or more times)
ccgcm_update(...) (may be called zero or more times)
ccgcm_finalize(...)
@warning The key-IV pair must be unique per encryption. The IV must be nonzero in length.
@warning It is not permitted to call @p ccgcm_inc_iv after initializing the cipher via the @p ccgcm_init interface. Nonzero is
returned in the event of an improper call sequence.
@warning This function is not FIPS-compliant. Use @p ccgcm_init_with_iv instead.
*/
int ccgcm_init(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t key_nbytes, const void *cc_sized_by(key_nbytes) key);
/*!
@function ccgcm_init_with_iv
@abstract Initialize a GCM context to manage IVs internally.
@param mode Descriptor for the mode
@param ctx Context for this instance
@param key_nbytes Length of the key in bytes
@param key Key for the underlying blockcipher (AES)
@param iv IV for the first encryption
@result 0 iff successful.
@discussion The correct sequence of calls is:
@code ccgcm_init_with_iv(...)
ccgcm_aad(...) (may be called zero or more times)
ccgcm_update(...) (may be called zero or more times)
ccgcm_finalize(...)
To reuse the context for additional encryptions, follow this sequence:
@code ccgcm_reset(...)
ccgcm_inc_iv(...)
ccgcm_aad(...) (may be called zero or more times)
ccgcm_update(...) (may be called zero or more times)
ccgcm_finalize(...)
The IV must be exactly 12 bytes in length.
Internally, the IV is treated as a four-byte salt followed by an eight-byte counter. This is to match the behavior of certain
protocols (e.g. TLS). In the call to @p ccgcm_inc_iv, the counter component will be interpreted as a big-endian, unsigned value
and incremented in place.
@warning It is not permitted to call @p ccgcm_set_iv after initializing the cipher via the @p ccgcm_init_with_iv interface.
Nonzero is returned in the event of an improper call sequence.
@warning The security of GCM depends on the uniqueness of key-IV pairs. To avoid key-IV repetition, callers should not initialize
multiple contexts with the same key material via the @p ccgcm_init_with_iv interface.
*/
int ccgcm_init_with_iv(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t key_nbytes, const void *cc_sized_by(key_nbytes) key, const void *cc_unsafe_indexable iv);
/*!
@function ccgcm_set_iv
@abstract Set the IV for encryption.
@param mode Descriptor for the mode
@param ctx Context for this instance
@param iv_nbytes Length of the IV in bytes
@param iv Initialization vector
@result 0 iff successful.
@discussion Set the initialization vector for encryption.
@warning The key-IV pair must be unique per encryption. The IV must be nonzero in length.
In stateful protocols, if each packet exposes a guaranteed-unique value, it is recommended to format this as a 12-byte value for
use as the IV.
In stateless protocols, it is recommended to choose a 16-byte value using a cryptographically-secure pseudorandom number
generator (e.g. @p ccrng).
@warning This function may not be used after initializing the cipher via @p ccgcm_init_with_iv. Nonzero is returned in the event
of an improper call sequence.
@warning This function is not FIPS-compliant. Use @p ccgcm_init_with_iv instead.
*/
int ccgcm_set_iv(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t iv_nbytes, const void *cc_sized_by(iv_nbytes) iv);
/*!
@function ccgcm_set_iv_legacy
@abstract Set the IV for encryption.
@param mode Descriptor for the mode
@param ctx Context for this instance
@param iv_nbytes Length of the IV in bytes
@param iv Initialization vector
@result 0 iff successful.
@discussion Identical to @p ccgcm_set_iv except that it allows zero-length IVs.
@warning Zero-length IVs nullify the authenticity guarantees of GCM.
@warning Do not use this function in new applications.
*/
int ccgcm_set_iv_legacy(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t iv_nbytes, const void *cc_sized_by(iv_nbytes) iv);
/*!
@function ccgcm_inc_iv
@abstract Increment the IV for another encryption.
@param mode Descriptor for the mode
@param ctx Context for this instance
@param iv Updated initialization vector
@result 0 iff successful.
@discussion Updates the IV internally for another encryption.
Internally, the IV is treated as a four-byte salt followed by an eight-byte counter. This is to match the behavior of certain
protocols (e.g. TLS). The counter component is interpreted as a big-endian, unsigned value and incremented in place.
The updated IV is copied to @p iv. This is to support protocols that require part of the IV to be specified explicitly in each
packet (e.g. TLS).
@warning This function may be used only after initializing the cipher via @p ccgcm_init_with_iv.
*/
int ccgcm_inc_iv(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, void *cc_unsafe_indexable iv);
/*!
@function ccgcm_aad
@abstract Authenticate additional data.
@param mode Descriptor for the mode
@param ctx Context for this instance
@param nbytes Length of the additional data in bytes
@param additional_data Additional data to authenticate
@result 0 iff successful.
@discussion This is typically used to authenticate data that cannot be encrypted (e.g. packet headers).
This function may be called zero or more times.
*/
int ccgcm_aad(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t nbytes, const void *cc_sized_by(nbytes) additional_data);
/*!
@function ccgcm_gmac
@discussion ccgcm_gmac is deprecated. Use the drop-in replacement 'ccgcm_aad' instead.
*/
int ccgcm_gmac(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t nbytes, const void *cc_sized_by(nbytes) in)
cc_deprecate_with_replacement("ccgcm_aad", 13.0, 10.15, 13.0, 6.0, 4.0);
/*!
@function ccgcm_update
@abstract Encrypt or decrypt data.
@param mode Descriptor for the mode
@param ctx Context for this instance
@param nbytes Length of the data in bytes
@param in Input plaintext or ciphertext
@param out Output ciphertext or plaintext
@result 0 iff successful.
@discussion In-place processing is supported.
This function may be called zero or more times.
*/
int ccgcm_update(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t nbytes, const void *cc_sized_by(nbytes) in, void *cc_sized_by(nbytes) out);
/*!
@function ccgcm_finalize
@abstract Finish processing and authenticate.
@param mode Descriptor for the mode
@param ctx Context for this instance
@param tag_nbytes Length of the tag in bytes
@param tag Authentication tag
@result 0 iff successful.
@discussion Finish processing a packet and generate the authentication tag.
On encryption, @p tag is purely an output parameter. The generated tag is written to @p tag.
On decryption, @p tag is both an input and an output parameter. Well-behaved callers should provide the authentication tag
generated during encryption. The function will return nonzero if the input tag does not match the generated tag. The generated
tag will be written into the @p tag buffer whether authentication succeeds or fails.
@warning The generated tag is written to @p tag to support legacy applications that perform authentication manually. Do not
follow this usage pattern in new applications. Rely on the function's error code to verify authenticity.
*/
int ccgcm_finalize(const struct ccmode_gcm *mode, ccgcm_ctx *ctx, size_t tag_nbytes, void *cc_sized_by(tag_nbytes) tag);
/*!
@function ccgcm_reset
@abstract Reset the context for another encryption.
@param mode Descriptor for the mode
@param ctx Context for this instance
@result 0 iff successful.
@discussion Refer to @p ccgcm_init for correct usage.
*/
int ccgcm_reset(const struct ccmode_gcm *mode, ccgcm_ctx *ctx);
/*!
@function ccgcm_one_shot
@abstract Encrypt or decrypt with GCM.
@param mode Descriptor for the mode
@param key_nbytes Length of the key in bytes
@param key Key for the underlying blockcipher (AES)
@param iv_nbytes Length of the IV in bytes
@param iv Initialization vector
@param adata_nbytes Length of the additional data in bytes
@param adata Additional data to authenticate
@param nbytes Length of the data in bytes
@param in Input plaintext or ciphertext
@param out Output ciphertext or plaintext
@param tag_nbytes Length of the tag in bytes
@param tag Authentication tag
@result 0 iff successful.
@discussion Perform GCM encryption or decryption.
@warning The key-IV pair must be unique per encryption. The IV must be nonzero in length.
In stateful protocols, if each packet exposes a guaranteed-unique value, it is recommended to format this as a 12-byte value for
use as the IV.
In stateless protocols, it is recommended to choose a 16-byte value using a cryptographically-secure pseudorandom number
generator (e.g. @p ccrng).
In-place processing is supported.
On encryption, @p tag is purely an output parameter. The generated tag is written to @p tag.
On decryption, @p tag is primarily an input parameter. The caller should provide the authentication tag generated during
encryption. The function will return nonzero if the input tag does not match the generated tag.
@warning To support legacy applications, @p tag is also an output parameter during decryption. The generated tag is written to @p
tag. Legacy callers may choose to compare this to the tag generated during encryption. Do not follow this usage pattern in new
applications.
*/
int ccgcm_one_shot(const struct ccmode_gcm *mode,
size_t key_nbytes,
const void *cc_sized_by(key_nbytes) key,
size_t iv_nbytes,
const void *cc_sized_by(iv_nbytes) iv,
size_t adata_nbytes,
const void *cc_sized_by(adata_nbytes) adata,
size_t nbytes,
const void *cc_sized_by(nbytes) in,
void *cc_sized_by(nbytes) out,
size_t tag_nbytes,
void *cc_sized_by(tag_nbytes) tag);
/*!
@function ccgcm_one_shot_legacy
@abstract Encrypt or decrypt with GCM.
@param mode Descriptor for the mode
@param key_nbytes Length of the key in bytes
@param key Key for the underlying blockcipher (AES)
@param iv_nbytes Length of the IV in bytes
@param iv Initialization vector
@param adata_nbytes Length of the additional data in bytes
@param adata Additional data to authenticate
@param nbytes Length of the data in bytes
@param in Input plaintext or ciphertext
@param out Output ciphertext or plaintext
@param tag_nbytes Length of the tag in bytes
@param tag Authentication tag
@result 0 iff successful.
@discussion Identical to @p ccgcm_one_shot except that it allows zero-length IVs.
@warning Zero-length IVs nullify the authenticity guarantees of GCM.
@warning Do not use this function in new applications.
*/
int ccgcm_one_shot_legacy(const struct ccmode_gcm *mode,
size_t key_nbytes,
const void *cc_sized_by(key_nbytes) key,
size_t iv_nbytes,
const void *cc_sized_by(iv_nbytes) iv,
size_t adata_nbytes,
const void *cc_sized_by(adata_nbytes) adata,
size_t nbytes,
const void *cc_sized_by(nbytes) in,
void *cc_sized_by(nbytes) out,
size_t tag_nbytes,
void *cc_sized_by(tag_nbytes) tag);
/* CCM */
#define CCM_MAX_TAG_SIZE 16
#define ccccm_ctx_decl(_size_, _name_) cc_ctx_decl_vla(ccccm_ctx, _size_, _name_)
#define ccccm_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
/* Declare a ccm nonce named _name_. Pass the mode->nonce_ctx_size for _size_. */
#define ccccm_nonce_decl(_size_, _name_) cc_ctx_decl_vla(ccccm_nonce, _size_, _name_)
#define ccccm_nonce_clear(_size_, _name_) cc_clear(_size_, _name_)
size_t ccccm_context_size(const struct ccmode_ccm *mode);
size_t ccccm_block_size(const struct ccmode_ccm *mode);
/// Initialize a ccm authenticated encryption/decryption mode
/// @param mode mode descriptor
/// @param ctx context for this instance
/// @param key_len length in bytes of key provided
/// @param key bytes defining key
int ccccm_init(const struct ccmode_ccm *mode, ccccm_ctx *ctx, size_t key_len, const void *cc_sized_by(key_len) key);
/// Set the initialization value/nonce for the ccm authenticated encryption/decryption
/// @param mode mode descriptor
/// @param ctx context for this ccm instance
/// @param nonce_ctx context for this nonce
/// @param nonce_len length in bytes of cmac nonce/iv
/// @param nonce bytes defining none
/// @param mac_size length in bytes of mac tag
/// @param auth_len length in bytes of authenticating data
/// @param data_len length in bytes of plaintext
int ccccm_set_iv(const struct ccmode_ccm *mode,
ccccm_ctx *ctx,
ccccm_nonce *nonce_ctx,
size_t nonce_len,
const void *cc_sized_by(nonce_len) nonce,
size_t mac_size,
size_t auth_len,
size_t data_len);
/// (Deprecated) Add associated data to the ccm authenticated encryption/decryption
/// @param mode mode descriptor
/// @param ctx context for this ccm instance
/// @param nonce_ctx context for this nonce
/// @param nbytes nbytes length in bytes of associated data being provided in this invocation
/// @param in authenticated data being provided in this invocation
int ccccm_cbcmac(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, size_t nbytes, const void *cc_sized_by(nbytes) in);
///Add associated data to the ccm authenticated encryption/decryption
/// @param mode mode descriptor
/// @param ctx context for this ccm instance
/// @param nonce_ctx context for this nonce
/// @param ad_nbytes nbytes length in bytes of associated data being provided in this invocation
/// @param ad authenticated data being provided in this invocation
int ccccm_aad(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, size_t ad_nbytes, const uint8_t *cc_sized_by(ad_nbytes) ad);
/// Add plaintext data to the ccm authenticated encryption/decryption
/// @param mode mode descriptor
/// @param ctx context for this ccm instance
/// @param nonce_ctx context for this nonce
/// @param nbytes length in bytes of both plaintext and encrypted plaintext
/// @param in In encryption mode plaintext data, in decryption mode encrypted plaintext data.
/// @param out in encryption mode resulting encrypted plaintext data. In decryption mode resulting plaintext data
int ccccm_update(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, size_t nbytes, const void *cc_sized_by(nbytes) in, void *cc_sized_by(nbytes) out);
/// Add plaintext data to the ccm authenticated encryption
/// @param mode mode descriptor
/// @param ctx context for this ccm instance
/// @param nonce_ctx context for this nonce
/// @param nbytes length in bytes of both plaintext and encrypted plaintext
/// @param plaintext In encryption mode plaintext data, in decryption mode encrypted plaintext data.
/// @param encrypted_plaintext in encryption mode resulting encrypted plaintext data. In decryption mode resulting plaintext data
int ccccm_encrypt(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, size_t nbytes, const uint8_t *cc_sized_by(nbytes) plaintext, uint8_t *cc_sized_by(nbytes) encrypted_plaintext);
/// Add ciphertext data to the ccm authenticated decryption
/// @param mode mode descriptor
/// @param ctx context for this ccm instance
/// @param nonce_ctx context for this nonce
/// @param nbytes length in bytes of both plaintext and encrypted plaintext
/// @param encrypted_plaintext In encryption mode plaintext data, in decryption mode encrypted plaintext data.
/// @param plaintext in encryption mode resulting encrypted plaintext data. In decryption mode resulting plaintext data
int ccccm_decrypt(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, size_t nbytes, const uint8_t *cc_sized_by(nbytes) encrypted_plaintext, uint8_t *cc_sized_by(nbytes) plaintext);
/// (Deprecated) Compute tag for ccm
/// @param mode mode descriptor
/// @param ctx context for this ccm instance
/// @param nonce_ctx context for this nonce
/// @param mac tag portion of ciphertext that is computed from ccm MAC.
/// @discussion This is being deprecated, as it requires the caller to manually verify that the returned mac tag is correct when decrypting. Please use ccccm_finalize_and_verify instead.
int ccccm_finalize(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, void *cc_indexable mac);
/// Ends encryption and computes tag when in encryption mode
/// @param mode mode descriptor
/// @param ctx context for this ccm instance
/// @param nonce_ctx context for this nonce
/// @param mac For encryption mode the resulting mac tag portion of the ciphertext is copied to this buffer. For decryption mode, it provides an input of the expected tag in the ciphertext
/// @return For decryption returns CCERR_OK if the provided mac matches the computed mac, and otherwise returns CCMODE_INTEGRITY_FAILURE.
int ccccm_finalize_and_generate_tag(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, uint8_t *cc_indexable mac);
/// Ends decryption and verifies tag when in decryption mode
/// @param mode mode descriptor
/// @param ctx context for this ccm instance
/// @param nonce_ctx context for this nonce
/// @param mac It provides an input of the expected tag in the ciphertext
/// @return Returns CCERR_OK if the provided mac matches the computed mac, and otherwise returns CCMODE_INTEGRITY_FAILURE.
int ccccm_finalize_and_verify_tag(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, const uint8_t *cc_indexable mac);
/// Resets the state of the encryptor/decryptor, maintaining the key, but clearing the nonce/iv, allowing for a new encryption or decryption
/// @param mode mode descriptor
/// @param ctx context for this ccm instance
/// @param nonce_ctx context for this nonce
int ccccm_reset(const struct ccmode_ccm *mode, ccccm_ctx *ctx, ccccm_nonce *nonce_ctx);
/// (Deprecated) Encrypts/Decrypts a plaintext/ciphertext using the AEAD CCM mode.
/// @param mode mode descriptor
/// @param key_len key length in bytes
/// @param key buffer holding key
/// @param nonce_len nonce length in bytes
/// @param nonce buffer holding nonce
/// @param nbytes the length of the plaintext and encrypted-plaintext
/// @param in buffer holding plaintext in encryption mode, and encrypted plaintext portion of ciphertext in decryption mode
/// @param out buffer receiving resulting encrypted plaintext in encryption mode, and resulting plaintext in decryption mode
/// @param adata_len length in bytes of associated data
/// @param adata authenticated data being provided in this invocation.
/// @param mac_size length in bytes of CCM mac tag
/// @param mac portion of ciphertext that is computed from ccm MAC.
/// @return This is being deprecated, as it requires the caller to manually verify that the returned mac tag is correct when decrypting. Please use ccccm_one_shot_with_verify instead
int ccccm_one_shot(const struct ccmode_ccm *mode,
size_t key_len,
const void *cc_sized_by(key_len) key,
size_t nonce_len,
const void *cc_sized_by(nonce_len) nonce,
size_t nbytes,
const void *cc_sized_by(nbytes) in,
void *cc_sized_by(nbytes) out,
size_t adata_len,
const void *cc_sized_by(adata_len) adata,
size_t mac_size,
void *cc_sized_by(mac_size) mac);
/// Encrypts a plaintext using the AEAD CCM mode, and provides corresponding mac tag. The encrypted plaintext and tag together are the AEAD ciphertext
/// @param mode mode descriptor
/// @param key_nbytes key length in bytes
/// @param key buffer holding key
/// @param nonce_nbytes nonce length in bytes
/// @param nonce buffer holding nonce
/// @param nbytes the length of the plaintext and encrypted-plaintext
/// @param plaintext buffer holding plaintext in encryption mode, and encrypted plaintext portion of ciphertext in decryption mode
/// @param encrypted_plaintext buffer receiving resulting encrypted plaintext in encryption mode
/// @param adata_nbytes length in bytes of associated data
/// @param adata authenticated data being provided in this invocation.
/// @param mac_tag_nbytes length in bytes of CCM mac tag
/// @param mac_tag portion of ciphertext that is computed from ccm MAC.
/// @return CERR_OK on successful encryption
int ccccm_one_shot_encrypt(const struct ccmode_ccm *mode,
size_t key_nbytes,
const uint8_t *cc_sized_by(key_nbytes) key,
size_t nonce_nbytes,
const uint8_t *cc_sized_by(nonce_nbytes) nonce,
size_t nbytes,
const uint8_t *cc_sized_by(nbytes) plaintext,
uint8_t *cc_sized_by(nbytes) encrypted_plaintext,
size_t adata_nbytes,
const uint8_t *cc_sized_by(adata_nbytes) adata,
size_t mac_tag_nbytes,
uint8_t *cc_sized_by(mac_tag_nbytes) mac_tag);
/// Decrypts a ciphertext using the AEAD CCM mode and ensures authenticity of the ciphertext. An AEAD CCM ciphertext consists of encrypted plaintext and mac tag
/// @param mode mode descriptor
/// @param key_nbytes key length in bytes
/// @param key buffer holding key
/// @param nonce_nbytes nonce length in bytes
/// @param nonce buffer holding nonce
/// @param nbytes the length of the plaintext and encrypted-plaintext
/// @param encrypted_plaintext buffer holding the encrypted plaintext portion of ciphertext
/// @param plaintext buffer receiving resulting plaintext
/// @param adata_nbytes length in bytes of associated data
/// @param adata authenticated data being provided in this invocation.
/// @param mac_tag_nbytes length in bytes of CCM mac tag
/// @param mac_tag portion of ciphertext that is computed from ccm MAC.
/// @return For decryption returns CCERR_OK if the provided mac matches the computed mac, and otherwise returns CCMODE_INTEGRITY_FAILURE.
int ccccm_one_shot_decrypt(const struct ccmode_ccm *mode,
size_t key_nbytes,
const uint8_t *cc_sized_by(key_nbytes) key,
size_t nonce_nbytes,
const uint8_t *cc_sized_by(nonce_nbytes) nonce,
size_t nbytes,
const uint8_t *cc_sized_by(nbytes) encrypted_plaintext,
uint8_t *cc_sized_by(nbytes) plaintext,
size_t adata_nbytes,
const uint8_t *cc_sized_by(adata_nbytes) adata,
size_t mac_tag_nbytes,
const uint8_t *cc_sized_by(mac_tag_nbytes) mac_tag);
/* OMAC mode. */
/* Declare a omac key named _name_. Pass the size field of a struct ccmode_omac
for _size_. */
#define ccomac_ctx_decl(_size_, _name_) cc_ctx_decl_vla(ccomac_ctx, _size_, _name_)
#define ccomac_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
size_t ccomac_context_size(const struct ccmode_omac *mode);
size_t ccomac_block_size(const struct ccmode_omac *mode);
int ccomac_init(const struct ccmode_omac *mode, ccomac_ctx *ctx, size_t tweak_len, size_t key_len, const void *cc_sized_by(key_len) key);
int ccomac_update(const struct ccmode_omac *mode, ccomac_ctx *ctx, size_t nblocks, const void *tweak, const void *cc_indexable in, void *cc_indexable out);
int ccomac_one_shot(const struct ccmode_omac *mode,
size_t tweak_len,
size_t key_len,
const void *cc_sized_by(key_len) key,
const void *cc_sized_by(tweak_len) tweak,
size_t nblocks,
const void *cc_indexable in,
void *cc_indexable out);
#endif /* _CORECRYPTO_CCMODE_H_ */

View file

@ -0,0 +1,138 @@
/* Copyright (c) (2011,2012,2013,2014,2015,2016,2017,2018,2019) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCMODE_FACTORY_H_
#define _CORECRYPTO_CCMODE_FACTORY_H_
#include <corecrypto/ccn.h>
#include <corecrypto/ccmode_impl.h>
/* Functions defined in this file are only to be used
within corecrypto files.
*/
/* Use these function to runtime initialize a ccmode_cbc decrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb decrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_cbc_decrypt(struct ccmode_cbc *cbc,
const struct ccmode_ecb *ecb);
/* Use these function to runtime initialize a ccmode_cbc encrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_cbc_encrypt(struct ccmode_cbc *cbc,
const struct ccmode_ecb *ecb);
/* Use these function to runtime initialize a ccmode_cfb decrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_cfb_decrypt(struct ccmode_cfb *cfb,
const struct ccmode_ecb *ecb);
/* Use these function to runtime initialize a ccmode_cfb encrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_cfb_encrypt(struct ccmode_cfb *cfb,
const struct ccmode_ecb *ecb);
/* Use these function to runtime initialize a ccmode_cfb8 decrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb decrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_cfb8_decrypt(struct ccmode_cfb8 *cfb8,
const struct ccmode_ecb *ecb);
/* Use these function to runtime initialize a ccmode_cfb8 encrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_cfb8_encrypt(struct ccmode_cfb8 *cfb8,
const struct ccmode_ecb *ecb);
/* Use these function to runtime initialize a ccmode_ctr decrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_ctr_crypt(struct ccmode_ctr *ctr,
const struct ccmode_ecb *ecb);
/* Use these function to runtime initialize a ccmode_gcm decrypt object (for
example if it's part of a larger structure). For GCM you always pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_gcm_decrypt(struct ccmode_gcm *gcm,
const struct ccmode_ecb *ecb_encrypt);
/* Use these function to runtime initialize a ccmode_gcm encrypt object (for
example if it's part of a larger structure). For GCM you always pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_gcm_encrypt(struct ccmode_gcm *gcm,
const struct ccmode_ecb *ecb_encrypt);
/* Use these function to runtime initialize a ccmode_ccm decrypt object (for
example if it's part of a larger structure). For CCM you always pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_ccm_decrypt(struct ccmode_ccm *ccm,
const struct ccmode_ecb *ecb_encrypt);
/* Use these function to runtime initialize a ccmode_ccm encrypt object (for
example if it's part of a larger structure). For CCM you always pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_ccm_encrypt(struct ccmode_ccm *ccm,
const struct ccmode_ecb *ecb_encrypt);
/* Use these function to runtime initialize a ccmode_ofb encrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_ofb_crypt(struct ccmode_ofb *ofb,
const struct ccmode_ecb *ecb);
/* Use these function to runtime initialize a ccmode_omac decrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb decrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_omac_decrypt(struct ccmode_omac *omac,
const struct ccmode_ecb *ecb);
/* Use these function to runtime initialize a ccmode_omac encrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_omac_encrypt(struct ccmode_omac *omac,
const struct ccmode_ecb *ecb);
/* Use these function to runtime initialize a ccmode_xts decrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb decrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_xts_decrypt(struct ccmode_xts *xts,
const struct ccmode_ecb *ecb,
const struct ccmode_ecb *ecb_encrypt);
/* Use these function to runtime initialize a ccmode_xts encrypt object (for
example if it's part of a larger structure). Normally you would pass a
ecb encrypt mode implementation of some underlying algorithm as the ecb
parameter. */
void ccmode_factory_xts_encrypt(struct ccmode_xts *xts,
const struct ccmode_ecb *ecb,
const struct ccmode_ecb *ecb_encrypt);
#endif /* _CORECRYPTO_CCMODE_FACTORY_H_ */

View file

@ -0,0 +1,286 @@
/* Copyright (c) (2010-2012,2015-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCMODE_IMPL_H_
#define _CORECRYPTO_CCMODE_IMPL_H_
#include <corecrypto/cc.h>
#define CCMODE_MAX_BLOCK_SIZE 16
/* ECB mode. */
cc_aligned_struct(16) ccecb_ctx;
/* Actual symmetric algorithm implementation should provide you one of these. */
struct ccmode_ecb {
size_t size; /* first argument to ccecb_ctx_decl(). */
size_t block_size;
int (*CC_SPTR(ccmode_ecb, init))(const struct ccmode_ecb *ecb, ccecb_ctx *ctx, size_t key_nbytes, const void *key);
int (*CC_SPTR(ccmode_ecb, ecb))(const ccecb_ctx *ctx, size_t nblocks, const void *in, void *out);
void (*CC_SPTR(ccmode_ecb, roundkey))(const ccecb_ctx *ctx, unsigned r, void *key);
cc_impl_t impl;
};
/*!
* @brief corecrypto symmetrical encryption and decryption modes
*
* corecrypto supports 6 stateless en(de)cryption modes and 2 stateful authenticated en(de)cryption modes
* stateless modes CBC, CFB, CFB8, CTR, OFB, XTS: They provide 3 interface functions that do not return errors codes
* 1- ccmod_xxx_init()
* 2- ccmod_xxx_decrypt()
* 3- ccmod_xxx_encrypt()
*
* stateful modes CCM and GCM: They provide 7 interface functions that return error codes if a function is called out of state
* 1- ccmod_xxx_init()
* 2- ccmod_xxx_setiv()
* 3- ccmod_xxx_aad()
* 4- ccmod_xxx_decrypt()
* 5- ccmod_xxx_encrypt()
* 6- ccmod_xxx_finalize()
* 7- ccmod_xxx_reset()
*
* the correct call sequences are:
*
* calls to 1, 2 and 6 arerequired
* 2 and 3 can be called as mant times as needed
* calls to 3, 4, 5 can be skipped
*
* 1, 2*n, 3*n, 4|5, 6
* 1, 2*n, , 4|5, 6
* 1, 2*n, , , 6
* 1, 2*n, 3*n, , 6
*/
// 1- CBC mode, stateless
cc_aligned_struct(16) cccbc_ctx;
cc_aligned_struct(16) cccbc_iv;
// This value was derived empirically. It may need to be updated to
// match changes in implementation.
#define CCCBC_MAX_CTX_SIZE 512
struct ccmode_cbc {
size_t size; /* first argument to cccbc_ctx_decl(). */
size_t block_size;
int (*CC_SPTR(ccmode_cbc, init))(const struct ccmode_cbc *cbc, cccbc_ctx *ctx, size_t key_len, const void *key);
/* cbc encrypt or decrypt nblocks from in to out, iv will be used and updated. */
int (*CC_SPTR(ccmode_cbc, cbc))(const cccbc_ctx *ctx, cccbc_iv *iv, size_t nblocks, const void *in, void *out);
const void *custom;
};
// 2- CFB mode, stateless
cc_aligned_struct(16) cccfb_ctx;
struct ccmode_cfb {
size_t size; /* first argument to cccfb_ctx_decl(). */
size_t block_size;
int (*CC_SPTR(ccmode_cfb,
init))(const struct ccmode_cfb *cfb, cccfb_ctx *ctx, size_t key_len, const void *key, const void *iv);
int (*CC_SPTR(ccmode_cfb, cfb))(cccfb_ctx *ctx, size_t nbytes, const void *in, void *out);
const void *custom;
};
// 3- CFB8 mode, stateless
cc_aligned_struct(16) cccfb8_ctx;
struct ccmode_cfb8 {
size_t size; /* first argument to cccfb8_ctx_decl(). */
size_t block_size;
int (*CC_SPTR(ccmode_cfb8,
init))(const struct ccmode_cfb8 *cfb8, cccfb8_ctx *ctx, size_t key_len, const void *key, const void *iv);
int (*CC_SPTR(ccmode_cfb8, cfb8))(cccfb8_ctx *ctx, size_t nbytes, const void *in, void *out);
const void *custom;
};
// 4- CTR mode, stateless
cc_aligned_struct(16) ccctr_ctx;
struct ccmode_ctr {
size_t size; /* first argument to ccctr_ctx_decl(). */
size_t block_size; /* for historical reasons, this is set to 1 */
size_t ecb_block_size; /* the actual block size of the underlying cipher */
int (*CC_SPTR(ccmode_ctr,
init))(const struct ccmode_ctr *mode, ccctr_ctx *ctx, size_t key_len, const void *key, const void *iv);
int (*CC_SPTR(ccmode_ctr, setctr))(const struct ccmode_ctr *mode, ccctr_ctx *ctx, const void *ctr);
int (*CC_SPTR(ccmode_ctr, ctr))(ccctr_ctx *ctx, size_t nbytes, const void *in, void *out);
const void *custom;
};
// 5- OFB mode, stateless
cc_aligned_struct(16) ccofb_ctx;
struct ccmode_ofb {
size_t size; /* first argument to ccofb_ctx_decl(). */
size_t block_size;
int (*CC_SPTR(ccmode_ofb,
init))(const struct ccmode_ofb *ofb, ccofb_ctx *ctx, size_t key_len, const void *key, const void *iv);
int (*CC_SPTR(ccmode_ofb, ofb))(ccofb_ctx *ctx, size_t nbytes, const void *in, void *out);
const void *custom;
};
// 6- XTS mode, stateless
cc_aligned_struct(16) ccxts_ctx;
cc_aligned_struct(16) ccxts_tweak;
struct ccmode_xts {
size_t size; /* first argument to ccxts_ctx_decl(). Size of the ctx data structure */
size_t tweak_size; /* first argument to ccxts_tweak_decl(). Size of the tweak structure, not the expected tweak size */
size_t block_size;
/* Create a xts key from a xts mode object.
key must point to at least 'size' bytes of free storage.
tweak_key must point to at least 'tweak_size' bytes of free storage.
key and tweak_key must differ.
Returns nonzero on failure.
*/
int (*CC_SPTR(ccmode_xts, init))(const struct ccmode_xts *xts,
ccxts_ctx *ctx,
size_t key_nbytes,
const void *data_key,
const void *tweak_key);
void (*CC_SPTR(ccmode_xts, key_sched))(const struct ccmode_xts *xts,
ccxts_ctx *ctx,
size_t key_nbytes,
const void *data_key,
const void *tweak_key);
/* Set the tweak (sector number), the block within the sector zero. */
int (*CC_SPTR(ccmode_xts, set_tweak))(const ccxts_ctx *ctx, ccxts_tweak *tweak, const void *iv);
/* Encrypt blocks for a sector, clients must call set_tweak before calling
this function. Return a pointer to the tweak buffer */
void *(*CC_SPTR(ccmode_xts, xts))(const ccxts_ctx *ctx, ccxts_tweak *tweak, size_t nblocks, const void *in, void *out);
const void *custom;
const void *custom1;
cc_impl_t impl;
};
// 7- GCM mode, statful
cc_aligned_struct(16) ccgcm_ctx;
#define CCMODE_GCM_DECRYPTOR 78647
#define CCMODE_GCM_ENCRYPTOR 4073947
struct ccmode_gcm {
size_t size; /* first argument to ccgcm_ctx_decl(). */
int encdec; // is it encrypt or decrypt object
size_t block_size;
int (*CC_SPTR(ccmode_gcm, init))(const struct ccmode_gcm *gcm, ccgcm_ctx *ctx, size_t key_nbytes, const void *key);
int (*CC_SPTR(ccmode_gcm, set_iv))(ccgcm_ctx *ctx, size_t iv_nbytes, const void *iv);
int (*CC_SPTR(ccmode_gcm, gmac))(ccgcm_ctx *ctx, size_t nbytes, const void *in); // could just be gcm with NULL out
int (*CC_SPTR(ccmode_gcm, gcm))(ccgcm_ctx *ctx, size_t nbytes, const void *in, void *out);
int (*CC_SPTR(ccmode_gcm, finalize))(ccgcm_ctx *key, size_t tag_nbytes, void *tag);
int (*CC_SPTR(ccmode_gcm, reset))(ccgcm_ctx *ctx);
const void *custom;
};
// 8- CCM mode, stateful
cc_aligned_struct(16) ccccm_ctx;
cc_aligned_struct(16) ccccm_nonce;
struct ccmode_ccm {
size_t size; /* first argument to ccccm_ctx_decl(). */
size_t nonce_size; /* first argument to ccccm_nonce_decl(). */
size_t block_size;
int (*CC_SPTR(ccmode_ccm, init))(const struct ccmode_ccm *ccm, ccccm_ctx *ctx, size_t key_len, const void *key);
int (*CC_SPTR(ccmode_ccm, set_iv))(ccccm_ctx *ctx,
ccccm_nonce *nonce_ctx,
size_t nonce_len,
const void *nonce,
size_t mac_size,
size_t auth_len,
size_t data_len);
int (*CC_SPTR(ccmode_ccm, cbcmac))(ccccm_ctx *ctx,
ccccm_nonce *nonce_ctx,
size_t nbytes,
const void *in); // could just be ccm with NULL out
int (*CC_SPTR(ccmode_ccm, ccm))(ccccm_ctx *ctx, ccccm_nonce *nonce_ctx, size_t nbytes, const void *in, void *out);
int (*CC_SPTR(ccmode_ccm, finalize))(ccccm_ctx *key, ccccm_nonce *nonce_ctx, void *mac);
int (*CC_SPTR(ccmode_ccm, reset))(ccccm_ctx *key, ccccm_nonce *nonce_ctx);
const void *custom;
bool enc_mode;
};
/* We need to expose this (currently)to keep CommonCrypto happy. */
struct _ccmode_ccm_nonce {
unsigned char A_i[16]; /* crypto block iv */
unsigned char B_i[16]; /* mac block iv */
unsigned char MAC[16]; /* crypted mac */
unsigned char buf[16]; /* crypt buffer */
uint32_t mode; /* mode: IV -> AD -> DATA */
uint32_t buflen; /* length of data in buf */
uint32_t b_i_len; /* length of cbcmac data in B_i */
size_t nonce_size;
size_t mac_size;
};
/* OMAC mode. */
cc_aligned_struct(16) ccomac_ctx;
struct ccmode_omac {
size_t size; /* first argument to ccomac_ctx_decl(). */
size_t block_size;
int (*CC_SPTR(ccmode_omac,
init))(const struct ccmode_omac *omac, ccomac_ctx *ctx, size_t tweak_len, size_t key_len, const void *key);
int (*CC_SPTR(ccmode_omac, omac))(ccomac_ctx *ctx, size_t nblocks, const void *tweak, const void *in, void *out);
const void *custom;
};
/* This provide an implementation of SIV
as specified in https://tools.ietf.org/html/rfc5297
also in http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/siv/siv.pdf
Counter Mode where IV is based on CMAC
*/
cc_aligned_struct(16) ccsiv_ctx;
struct ccmode_siv {
size_t size; /* first argument to ccsiv_ctx_decl(). */
size_t block_size;
int (*CC_SPTR(ccmode_siv, init))(const struct ccmode_siv *siv, ccsiv_ctx *ctx,
size_t key_len, const uint8_t *key);
int (*CC_SPTR(ccmode_siv, set_nonce))(ccsiv_ctx *ctx, size_t nbytes, const uint8_t *in); // could just be ccm with NULL out
int (*CC_SPTR(ccmode_siv, auth))(ccsiv_ctx *ctx, size_t nbytes, const uint8_t *in); // could just be ccm with NULL out
int (*CC_SPTR(ccmode_siv, crypt))(ccsiv_ctx *ctx, size_t nbytes, const uint8_t *in, uint8_t *out);
int (*CC_SPTR(ccmode_siv, reset))(ccsiv_ctx *ctx);
const struct ccmode_cbc *cbc;
const struct ccmode_ctr *ctr;
};
/* This provides an implementation of SIV using AES CTR mode with HMAC as the MAC,
allowing for a tagging mechanism with collision resistant tags. This is a modification of the
standard specified in https://tools.ietf.org/html/rfc5297
also in http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/siv/siv.pdf
Counter Mode where IV is based on HMAC.
*/
cc_aligned_struct(16) ccsiv_hmac_ctx;
struct ccmode_siv_hmac {
size_t size; /* first argument to ccsiv_hmac_ctx_decl(). */
size_t block_size;
int (*CC_SPTR(ccmode_siv_hmac, init))(const struct ccmode_siv_hmac *sivhmac,
ccsiv_hmac_ctx *ctx,
size_t key_len,
const uint8_t *key,
const size_t tag_size);
int (*CC_SPTR(ccmode_siv_hmac, set_nonce))(ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in);
int (*CC_SPTR(ccmode_siv_hmac, auth))(ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in);
int (*CC_SPTR(ccmode_siv_hmac, crypt))(ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in, uint8_t *out);
int (*CC_SPTR(ccmode_siv_hmac, reset))(ccsiv_hmac_ctx *ctx);
const struct ccdigest_info *hmac_digest; // Digest to be used in HMAC;
const struct ccmode_ctr *ctr;
};
#endif /* _CORECRYPTO_CCMODE_IMPL_H_ */

View file

@ -0,0 +1,201 @@
/* Copyright (c) (2015-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCMODE_SIV_H_
#define _CORECRYPTO_CCMODE_SIV_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccmode.h>
#include <corecrypto/ccmode_impl.h>
#include <corecrypto/cccmac.h>
#define ccsiv_ctx_decl(_size_, _name_) cc_ctx_decl_vla(ccsiv_ctx, _size_, _name_)
#define ccsiv_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
// Functions
size_t ccsiv_context_size(const struct ccmode_siv *mode);
/*!
@function ccsiv_block_size
@abstract Return the block_size = block_length = tag_length used in the mode.
@param mode ccsiv mode descriptor
@discussion Used to return the current block size of the SIV mode. Note that the tag in this mode is an output of the underlying blockcipher and therefore the tag length corresponds to the block size.
*/
size_t ccsiv_block_size(const struct ccmode_siv *mode);
/*!
@function ccsiv_ciphertext_size
@abstract Return size of Ciphertext (which is the ciphertext and corresponding tag) given the mode and plaintext length
@param mode ccsiv mode descriptor
@param plaintext_size Size of the plaintext
@discussion returns the length of the aead ciphertext that the context will generate which includes both the encrypted plaintext and tag.
*/
size_t ccsiv_ciphertext_size(const struct ccmode_siv *mode, size_t plaintext_size);
/*!
@function ccsiv_plaintext_size
@abstract Return size of plaintext given a ciphertext length and mode.
@param mode ccsiv mode descriptor
@param ciphertext_size Size of the ciphertext
@discussion returns the length of the plaintext which results from the decryption of a ciphertext of the corresponding size (here ciphertext size includes the tag).
*/
size_t ccsiv_plaintext_size(const struct ccmode_siv *mode, size_t ciphertext_size);
/*!
@function ccsiv_init
@abstract Initialize a context for ccsiv with an associated mode, and given key.
@param mode Descriptor for the mode
@param ctx Alocated context to be intialized
@param key_byte_len Length of the key: Supported key sizes are 32, 48, 64 bytes.
@param key key for siv. All bits of this key should be random. (See discussion)
@discussion In order to compute SIV_Enc_k(a1,...,am, n, x) where ai is the ith piece of associated data, n is a nonce and x is a plaintext, we use the following sequence of calls :
@code
ccsiv_init(...)
ccsiv_aad(...) (may be called zero or more times)
ccsiv_set_nonce(...)
ccsiv_crypt(...)
@endcode
To reuse the context for additional encryptions, follow this sequence:
@code
ccsiv_reset(...)
ccsiv_aad(...) (may be called zero or more times)
ccsiv_set_nonce(...)
ccsiv_crypt(...)
@endcode
Importantly, all the bits in the key need to be random. Duplicating a smaller key to achieve a longer key length will result in an insecure implementation.
*/
int ccsiv_init(const struct ccmode_siv *mode, ccsiv_ctx *ctx,
size_t key_byte_len, const uint8_t *key);
/*!
@function ccsiv_set_nonce
@abstract Add the nonce to the siv's computation of the the tag. Changes the internal state of the context
so that after the call only a crypt or reset call is permitted.
@param mode Descriptor for the mode
@param ctx Intialized ctx
@param nbytes Length of the current nonce data being added
@param in Nonce data to be authenticated.
@discussion The nonce is a special form of authenticated data. If provided (a call to ccsiv_set_nonce is optional) it allows
randomization of the ciphertext (preventing deterministic encryption). While the length of the nonce is not limmited, the
amount of entropy that can be provided is limited by the number of bits in the block of the associated block-cipher.
*/
int ccsiv_set_nonce(const struct ccmode_siv *mode, ccsiv_ctx *ctx,
size_t nbytes, const uint8_t *in);
/*!
@function ccsiv_aad
@abstract Add the next piece of associated data to the SIV's computation of the tag.
@param mode Descriptor for the mode
@param ctx Intialized ctx
@param nbytes Length of the current associated data being added
@param in Associated data to be authenticated.
@discussion Adds the associated data given by in to the computation of the tag in the associated data. Note this call is optional and no associated data needs to be provided. Multiple pieces of associated data can be provided by multiple calls to this function. Note the associated data in this case is simply computed as the concatenation of all of the associated data inputs.
*/
int ccsiv_aad(const struct ccmode_siv *mode, ccsiv_ctx *ctx,
size_t nbytes, const uint8_t *in);
/*!
@function ccsiv_crypt
@abstract Depdening on mode, 1) Encrypts a plaintext , or 2) Decrypts a ciphertext
@param mode Descriptor for the mode
@param ctx Intialized ctx
@param nbytes Case 1) Length of the current plaintext
Case 2) Length of the current ciphertext (block length + plaintext length).
@param in Case 1) Plaintext
Case 2) Ciphertext
@param out Case 1) Tag+ciphertext (buffer should be already allocated and of length block_length+plaintext_length.)
Case 2) Plaintext (buffer should be already allocated and of length ciphertext_length - block_length length
@discussion Depending on whether mode has been setup to encrypt or decrypt, this function
1) Encrypts the plaintext given as input in, and provides the ciphertext (which is a concatenation of the cbc-tag
followed by the encrypted plaintext) as output out. 2) Decrypts plaintext using the input ciphertext at in (which again is the cbc-tag, followed by encrypted plaintext), and then verifies that the computed tag and provided tags match.
This function is only called once. If one wishes to compute another (en)/(de)cryption, one resets the state with
ccsiv_reset, and then begins the process again. There is no way to stream large plaintext/ciphertext inputs into the
function.
In the case of a decryption, if there is a failure in verifying the computed tag against the provided tag (embedded int he ciphertext), then a decryption/verification
failure is returned, and any internally computed plaintexts and tags are zeroed out.
Lastly the contexts internal state is reset, so that a new decryption/encryption can be commenced.
Decryption can be done in place in memory by setting in=out. Encryption cannot be done in place. However, if one is trying to minimize memory usage one can set out = in - block_length, which results in the ciphertext being encrypted inplace, and the IV being prepended before the ciphertext.
*/
int ccsiv_crypt(const struct ccmode_siv *mode, ccsiv_ctx *ctx,
size_t nbytes, const uint8_t *in, uint8_t *out);
/*!
@function ccsiv_reset
@abstract Resets the state of the ccsiv_ctx ctx, maintaing the key, but preparing the
ctx to preform a new Associated Data Authenticated (En)/(De)cryption.
@param mode Descriptor for the mode
@param ctx Intialized ctx
*/
int ccsiv_reset(const struct ccmode_siv *mode, ccsiv_ctx *ctx);
/*!
@function ccsiv_one_shot
@abstract A simplified but more constrained way of performing a AES SIV (en)/(de)cryption. It is limited because only
one piece of associated data may be provided.
@param mode Descriptor for the mode
@param key_len Length of the key: Supported key sizes are 32, 48, 64 bytes
@param key key for siv
@param nonce_nbytes Length of the current nonce data being added
@param nonce Nonce data to be authenticated.
@param adata_nbytes Length of the associated data.
@param adata Associated data to be authenticated.
@param in_nbytes Length of either the plaintext (for encryption) or ciphertext (for decryption), in the latter case the length includes the length of the tag.
@param in Plaintext or ciphertext. Note that the ciphertext includes a tag of length tag_length prepended to it.
@param out Buffer to hold ciphertext/plaintext. (Note Ciphertext is of size plaintext_length + block_length and plaintext is of ciphertext_length - block_length, as the tag has the length of one block.
Must be the case that out<= in - block length || out>= in + plaintext_length
@discussion Decryption can be done in place in memory by setting in=out. Encryption cannot be done in place. However, is one is trying to minimize memory usage
one can set out = in - block_length, which results in the ciphertext being encrypted inplace, and the IV being prepended before the ciphertext.
Suppose the block length is 16 bytes long (AES) and plaintext of length 20, then we could set in = 16, out = 0 let the bytes of the plaintext be denoted as P_1...P_20
then memory is depicted as:
| 0 = ? | 1 = ? | ... | 15 = ? | 16 = P_1 | ... | 35 = P_20 |
| | | | |
V V V V V
|IV_1 | IV_2 | ... | IV_16 | C_1 | ... | C_20 |
Note that the ciphrtext itself is encrypted in place, but the IV prefixes the ciphertext.
*/
int ccsiv_one_shot(const struct ccmode_siv *mode,
size_t key_len, const uint8_t *key,
unsigned nonce_nbytes, const uint8_t* nonce,
unsigned adata_nbytes, const uint8_t* adata,
size_t in_nbytes, const uint8_t *in, uint8_t *out);
#endif /* _CORECRYPTO_CCMODE_H_ */

View file

@ -0,0 +1,179 @@
/* Copyright (c) (2019-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCMODE_SIV_HMAC_H
#define _CORECRYPTO_CCMODE_SIV_HMAC_H
#include <corecrypto/cc.h>
#include <corecrypto/ccmode.h>
#include <corecrypto/ccmode_impl.h>
#include <corecrypto/ccdigest.h>
#include <corecrypto/cchmac.h>
#include <corecrypto/ccsha2.h>
#define ccsiv_hmac_ctx_decl(_size_, _name_) cc_ctx_decl_vla(ccsiv_hmac_ctx, _size_, _name_)
#define ccsiv_hmac_ctx_clear(_size_, _name_) cc_clear(_size_, _name_)
/*!
@function ccsiv_hmac_context_size
@abstract Return size of context
@param mode Descriptor for the mode
*/
size_t ccsiv_hmac_context_size(const struct ccmode_siv_hmac *mode);
/*!
@function ccsiv_hmac_block_size
@abstract Return size of context
@param mode Descriptor for the mode
*/
size_t ccsiv_hmac_block_size(const struct ccmode_siv_hmac *mode);
/*!
@function ccsiv_hmac_ciphertext_size
@abstract Return size of Ciphertext (which is the ciphertext and corresponding tag) given the mode and plaintext length
@param ctx Current siv_hmac context that has been previously initialized
@param plaintext_size Size of the plaintext
@discussion returns the length of the aead ciphertext that the context will generate which includes both the encrypted plaintext
and tag.
*/
size_t ccsiv_hmac_ciphertext_size(ccsiv_hmac_ctx *ctx, size_t plaintext_size);
/*!
@function ccsiv_hmac_plaintext_size
@abstract Return size of plaintext given a ciphertext length and mode.
@param ctx Current siv_hmac context that has been previously initialized
@param ciphertext_size Size of the ciphertext (which includes the tag)
@discussion returns the length of the plaintext which results from the decryption of a ciphertext of the corresponding size (here ciphertext size includes the tag).
*/
size_t ccsiv_hmac_plaintext_size(ccsiv_hmac_ctx *ctx, size_t ciphertext_size);
/*!
@function ccsiv_hmac_init
@abstract Initialize a context for siv_hmac with an associated mode, given key and specifying output tag size.
@param mode Descriptor for the mode
@param ctx Alocated context to be intialized
@param key_byte_len Length of the key: Supported key sizes are 32, 48, 64 bytes
@param key key for siv_hmac
@param tag_size The length of the output tag requested. Must be at least 20 bytes, and can be as large as the
associated digest's output
@discussion In order to compute HMAC_SIV_Enc_k(a1,...,am, n, x) where ai is the ith piece of associated data, n is a nonce and x
is a plaintext, we first initialize the context with this call, and then use it to call ccsiv_hmac_aad for each ai, followed by
ccsiv_hmac_set_nonce for nonce n, and finally a call to ccsiv_hmac_crypt for the plaintext x. Note the order of the calls to aad,
nonce and then crypt is critical. If a second encryption is needed then a call to ccsiv_hmac_reset can be used to reset state,
and begin again.
*/
int ccsiv_hmac_init(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx, size_t key_byte_len, const uint8_t *key, size_t tag_size);
/*!
@function ccsiv_hmac_aad
@abstract Add the next piece of associated data to the hmac_siv's computation of the tag. Note this call is optional and no
associated data needs to be provided. Multiple pieces of associated data can be provided by multiple calls to this
function. Each input is regarded as a separate piece of associated data, and the mac is NOT simply computed on the
concatenation of all of the associated data inputs. Therefore on decryption the same inputs must be provided in
the same order.
@param mode Descriptor for the mode
@param ctx Intialized ctx
@param nbytes Length of the current associated data being added
@param in Associated data to be authenticated.
@discussion Adds the associated data given by in to the computation of the tag in the associated data.
*/
int ccsiv_hmac_aad(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in);
/*!
@function ccsiv_hmac_nonce
@abstract Add the nonce to the hmac_siv's computation of the the tag. Changes the internal state of the context
so that after the call only a crypt or reset call is permitted.
@param mode Descriptor for the mode
@param ctx Intialized ctx
@param nbytes Length of the current nonce data being added
@param in Nonce data to be authenticated.
@discussion The nonce is a special form of authenticated data. If provided ( a call to hmac_nonce is optional) it allows
randomization of the ciphertext (preventing deterministic encryption). While the length of the nonce is not limited, the
amount of entropy that can be provided is limited by the number of bits in the block of the associated block-cipher in mode.
*/
int ccsiv_hmac_set_nonce(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in);
/*!
@function ccsiv_hmac_crypt
@abstract Depending on whether mode has been setup to encrypt or decrypt, this function
1) Encrypts the plaintext given as input in, and provides the ciphertext (which is a concatenation of the tag
followed by the encrypted plaintext) as output out. 2) Decrypts plaintext using the input ciphertext at in (which again is the
tag, followed by encrypted plaintext), and then verifies that the computer tag and provided tags match.
@param mode Descriptor for the mode
@param ctx Intialized ctx
@param nbytes Case 1) Length of the current plaintext
Case 2) Length of the current ciphertext (tag length + plaintext length)
@param in Case 1) Plaintext
Case 2) Ciphertext
@discussion This function is only called once. If one wishes to compute another (en)/(de)cryption, one resets the state with
ccsiv_hmac_reset, and then begins the process again. There is no way to stream large plaintext/ciphertext inputs into the
function.
@param out Case1) Tag+ Ciphertext (buffer should be already allocated and of length tag + plaintext length)
Case 2) Plaintext (buffer should be already allocated and of length ciphertext - tag length
In the case of a decryption, if there is a failure in verifying the computed tag against the provided tag (embedded int he ciphertext), then a decryption/verification
failure is returned, and any internally computed plaintexts and tags are zeroed out.
Lastly the contexts internal state is reset, so that a new decryption/encryption can be commenced.
*/
int ccsiv_hmac_crypt(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx, size_t nbytes, const uint8_t *in, uint8_t *out);
/*!
@function ccsiv_hmac_reset
@abstract Resets the state of the siv_hamc ctx, maintaining the key, but preparing the
ctx to preform a new Associated Data Authenticated (En)/(De)cryption.
@param mode Descriptor for the mode
@param ctx Intialized ctx
*/
int ccsiv_hmac_reset(const struct ccmode_siv_hmac *mode, ccsiv_hmac_ctx *ctx);
/*!
@function ccsiv_hmac_one_shot
@abstract A simplified but more constrained way of performing an AEAD SIV HMAC (en)/(de)cryption. It is limited because only
one piece of associated data may be provided.
@param mode Descriptor for the mode
@param key_len Length of the key: Supported key sizes are 32, 48, 64 bytes
@param key key for siv_hmac
@param tag_length The length of the tag to produce or accept as input. Must be at least 20
bytes, and can be as large as the hmac's digest's output
@param nonce_nbytes Length of the current nonce data being added
@param nonce Nonce data to be authenticated.
@param adata_nbytes Length of the associated data.
@param adata Associated data to be authenticated.
@param in_nbytes Length of either the plaintext (for encryption) or ciphertext (for decryption)
@param in plaintext or ciphertext. Note that the ciphertext includes a tag of length tag_length prepended to it.
@param out Buffer to hold ciphertext/plaintext. (Note Ciphertext is of size plaintext length + tag_length and plaintext is of length ciphertext - tag_length.)
*/
// One shot AEAD with only one input for adata, and a nonce.
int ccsiv_hmac_one_shot(const struct ccmode_siv_hmac *mode,
size_t key_len,
const uint8_t *key,
size_t tag_length,
unsigned nonce_nbytes,
const uint8_t *nonce,
unsigned adata_nbytes,
const uint8_t *adata,
size_t in_nbytes,
const uint8_t *in,
uint8_t *out);
#endif /* _CORECRYPTO_CCMODE_SIV_HMAC_H */

View file

@ -0,0 +1,413 @@
/* Copyright (c) (2010-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCN_H_
#define _CORECRYPTO_CCN_H_
#include <corecrypto/cc.h>
CC_PTRCHECK_CAPABLE_HEADER()
typedef size_t cc_size;
#if CCN_UNIT_SIZE == 8
typedef uint64_t cc_unit; // 64 bit unit
typedef int64_t cc_int;
#define CCN_LOG2_BITS_PER_UNIT 6 // 2^6 = 64 bits
#define CC_UNIT_C(x) UINT64_C(x)
#elif CCN_UNIT_SIZE == 4
typedef uint32_t cc_unit; // 32 bit unit
typedef int32_t cc_int;
#define CCN_LOG2_BITS_PER_UNIT 5 // 2^5 = 32 bits
#define CC_UNIT_C(x) UINT32_C(x)
#else
#error Unsupported CCN_UNIT_SIZE
#endif
#define CCN_UNIT_BITS (sizeof(cc_unit) * 8)
#define CCN_UNIT_MASK ((cc_unit)~0)
#define CCN_UNIT_LOWER_HALF_MASK ((CCN_UNIT_MASK) >> (CCN_UNIT_BITS/2))
#define CCN_UNIT_UPPER_HALF_MASK (~CCN_UNIT_LOWER_HALF_MASK)
#define CCN_UNIT_HALF_BITS (CCN_UNIT_BITS / 2)
/* Conversions between n sizeof and bits */
/* Returns the sizeof a ccn vector of length _n_ units. */
#define ccn_sizeof_n(_n_) (sizeof(cc_unit) * (_n_))
/* Returns the count (n) of a ccn vector that can represent _bits_. */
#define ccn_nof(_bits_) (((_bits_) + CCN_UNIT_BITS - 1) >> CCN_LOG2_BITS_PER_UNIT)
/* Returns the sizeof a ccn vector that can represent _bits_. */
#define ccn_sizeof(_bits_) (ccn_sizeof_n(ccn_nof(_bits_)))
/* Returns the count (n) of a ccn vector that can represent _size_ bytes. */
#define ccn_nof_size(_size_) (((_size_) + sizeof(cc_unit) - 1) / sizeof(cc_unit))
#define ccn_nof_sizeof(_expr_) ccn_nof_size(sizeof(_expr_))
/* Return the max number of bits a ccn vector of _n_ units can hold. */
#define ccn_bitsof_n(_n_) ((_n_) * CCN_UNIT_BITS)
/* Return the max number of bits a ccn vector of _size_ bytes can hold. */
#define ccn_bitsof_size(_size_) ((_size_) * 8)
/* Return the size of a ccn of size bytes in bytes. */
#define ccn_sizeof_size(_size_) ccn_sizeof_n(ccn_nof_size(_size_))
/*!
@function ccn_set_bit
@param x The input cc_unit
@param k The index to set
@param v The value to set
*/
CC_NONNULL_ALL
void ccn_set_bit(cc_unit *cc_indexable x, size_t k, cc_unit v);
/* Macros for making ccn constants. You must use list of CCN64_C() instances
separated by commas, with an optional smaller sized CCN32_C, CCN16_C, or
CCN8_C() instance at the end of the list, when making macros to declare
larger sized constants. */
#define CCN8_C(a0) CC_UNIT_C(0x##a0)
#define CCN16_C(a1,a0) CC_UNIT_C(0x##a1##a0)
#define ccn16_v(a0) (a0)
#define CCN32_C(a3,a2,a1,a0) CC_UNIT_C(0x##a3##a2##a1##a0)
#define ccn32_v(a0) (a0)
#if CCN_UNIT_SIZE == 8
#define CCN64_C(a7,a6,a5,a4,a3,a2,a1,a0) CC_UNIT_C(0x##a7##a6##a5##a4##a3##a2##a1##a0)
#define CCN40_C(a4,a3,a2,a1,a0) CC_UNIT_C(0x##a4##a3##a2##a1##a0)
#define ccn64_v(a0) (a0)
#else
#define CCN64_C(a7,a6,a5,a4,a3,a2,a1,a0) CCN32_C(a3,a2,a1,a0),CCN32_C(a7,a6,a5,a4)
#define CCN40_C(a4,a3,a2,a1,a0) CCN32_C(a3,a2,a1,a0),CCN8_C(a4)
#define ccn64_v(a0) ccn32_v((uint64_t)a0 & UINT32_C(0xffffffff)),ccn32_v((uint64_t)a0 >> 32)
#endif
/* Macro's for reading uint32_t and uint64_t from ccns, the index is in 32 or
64 bit units respectively. */
#if CCN_UNIT_SIZE == 8
#define ccn64_32(a1,a0) (((const cc_unit)a1) << 32 | ((const cc_unit)a0))
#define ccn32_32(a0) a0
#if __LITTLE_ENDIAN__
#define ccn32_32_parse(p,i) (((const uint32_t *)p)[i])
#else
#define ccn32_32_parse(p,i) (((const uint32_t *)p)[i^1])
#endif
#define ccn32_32_null 0
#define ccn64_64(a0) a0
#define ccn64_64_parse(p,i) p[i]
#define ccn64_64_null 0
#elif CCN_UNIT_SIZE == 4
#define ccn32_32(a0) a0
#define ccn32_32_parse(p,i) p[i]
#define ccn32_32_null 0
#define ccn64_32(a1,a0) ccn32_32(a0),ccn32_32(a1)
#define ccn64_64(a1,a0) a0,a1
#define ccn64_64_parse(p,i) p[1+(i<<1)],p[i<<1]
#define ccn64_64_null 0,0
#endif
/* Macros to construct fixed size ccn arrays from 64 or 32 bit quantities. */
#define ccn192_64(a2,a1,a0) ccn64_64(a0),ccn64_64(a1),ccn64_64(a2)
#define ccn192_32(a5,a4,a3,a2,a1,a0) ccn64_32(a1,a0),ccn64_32(a3,a2),ccn64_32(a5,a4)
#define ccn224_32(a6,a5,a4,a3,a2,a1,a0) ccn64_32(a1,a0),ccn64_32(a3,a2),ccn64_32(a5,a4),ccn32_32(a6)
#define ccn256_32(a7,a6,a5,a4,a3,a2,a1,a0) ccn64_32(a1,a0),ccn64_32(a3,a2),ccn64_32(a5,a4),ccn64_32(a7,a6)
#define ccn384_32(a11,a10,a9,a8,a7,a6,a5,a4,a3,a2,a1,a0) ccn64_32(a1,a0),ccn64_32(a3,a2),ccn64_32(a5,a4),ccn64_32(a7,a6),ccn64_32(a9,a8),ccn64_32(a11,a10)
#define CCN192_C(c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
CCN64_C(a7,a6,a5,a4,a3,a2,a1,a0),\
CCN64_C(b7,b6,b5,b4,b3,b2,b1,b0),\
CCN64_C(c7,c6,c5,c4,c3,c2,c1,c0)
#define CCN200_C(d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
CCN192_C(c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
CCN8_C(d0)
#define CCN224_C(d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
CCN192_C(c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
CCN32_C(d3,d2,d1,d0)
#define CCN232_C(d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
CCN192_C(c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
CCN40_C(d4,d3,d2,d1,d0)
#define CCN256_C(d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
CCN192_C(c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
CCN64_C(d7,d6,d5,d4,d3,d2,d1,d0)
#define CCN384_C(f7,f6,f5,f4,f3,f2,f1,f0,e7,e6,e5,e4,e3,e2,e1,e0,d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
CCN256_C(d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
CCN64_C(e7,e6,e5,e4,e3,e2,e1,e0),\
CCN64_C(f7,f6,f5,f4,f3,f2,f1,f0)
#define CCN448_C(g7,g6,g5,g4,g3,g2,g1,g0,f7,f6,f5,f4,f3,f2,f1,f0,e7,e6,e5,e4,e3,e2,e1,e0,d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
CCN256_C(d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
CCN192_C(g7,g6,g5,g4,g3,g2,g1,g0,f7,f6,f5,f4,f3,f2,f1,f0,e7,e6,e5,e4,e3,e2,e1,e0)
#define CCN528_C(i1,i0,h7,h6,h5,h4,h3,h2,h1,h0,g7,g6,g5,g4,g3,g2,g1,g0,f7,f6,f5,f4,f3,f2,f1,f0,e7,e6,e5,e4,e3,e2,e1,e0,d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0) \
CCN256_C(d7,d6,d5,d4,d3,d2,d1,d0,c7,c6,c5,c4,c3,c2,c1,c0,b7,b6,b5,b4,b3,b2,b1,b0,a7,a6,a5,a4,a3,a2,a1,a0),\
CCN256_C(h7,h6,h5,h4,h3,h2,h1,h0,g7,g6,g5,g4,g3,g2,g1,g0,f7,f6,f5,f4,f3,f2,f1,f0,e7,e6,e5,e4,e3,e2,e1,e0),\
CCN16_C(i1,i0)
#define CCN192_N ccn_nof(192)
#define CCN224_N ccn_nof(224)
#define CCN256_N ccn_nof(256)
#define CCN384_N ccn_nof(384)
#define CCN448_N ccn_nof(448)
#define CCN512_N ccn_nof(512)
#define CCN521_N ccn_nof(521)
/* s == 0 -> return 0 | s > 0 -> return index (starting at 1) of most
* significant bit that is 1.
* { N bit } N = n * sizeof(cc_unit) * 8
*
* Runs in constant time, independent of the value of `s`.
*/
CC_NONNULL((2))
size_t ccn_bitlen(cc_size n, const cc_unit *cc_counted_by(n) s);
/* s == 0 -> return true | s != 0 -> return false
{ N bit } N = n * sizeof(cc_unit) * 8 */
#define ccn_is_zero(_n_, _s_) (!ccn_n((_n_), (_s_)))
/* s == 1 -> return true | s != 1 -> return false
{ N bit } N = n * sizeof(cc_unit) * 8 */
#define ccn_is_one(_n_, _s_) (ccn_n((_n_), (_s_)) == 1 && (_s_)[0] == 1)
#define ccn_is_zero_or_one(_n_, _s_) (((_n_)==0) || ((ccn_n((_n_), (_s_)) <= 1) && ((_s_)[0] <= 1)))
/* s < t -> return - 1 | s == t -> return 0 | s > t -> return 1
{ N bit, N bit -> int } N = n * sizeof(cc_unit) * 8 */
CC_PURE CC_NONNULL((2, 3))
int ccn_cmp(cc_size n, const cc_unit *cc_counted_by(n) s, const cc_unit *cc_counted_by(n) t) __asm__("_ccn_cmp");
/*! @function ccn_cmpn
@abstract Compares the values of two big ints of different lengths.
@discussion The execution time does not depend on the values of either s or t.
The function does not hide ns, nt, or whether ns > nt.
@param ns Length of s
@param s First integer
@param nt Length of t
@param t Second integer
@return 1 if s > t, -1 if s < t, 0 otherwise.
*/
CC_NONNULL_ALL
int ccn_cmpn(cc_size ns, const cc_unit *cc_counted_by(ns) s, cc_size nt, const cc_unit *cc_counted_by(nt) t);
/* s - t -> r return 1 iff t > s
{ N bit, N bit -> N bit } N = n * sizeof(cc_unit) * 8 */
CC_NONNULL((2, 3, 4))
cc_unit ccn_sub(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, const cc_unit *cc_counted_by(n) t) __asm__("_ccn_sub");
/* s + t -> r return carry if result doesn't fit in n bits.
{ N bit, N bit -> N bit } N = n * sizeof(cc_unit) * 8 */
CC_NONNULL((2, 3, 4))
cc_unit ccn_add(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, const cc_unit *cc_counted_by(n) t) __asm__("_ccn_add");
/* s + v -> r return carry if result doesn't fit in n bits.
{ N bit, sizeof(cc_unit) * 8 bit -> N bit } N = n * sizeof(cc_unit) * 8 */
CC_NONNULL((2, 3))
cc_unit ccn_add1(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, cc_unit v);
/*!
@function ccn_read_uint
@abstract Copy big endian integer and represent it in cc_units
@param n Input allocated size of the cc_unit output array r
@param r Ouput cc_unit array for unsigned integer
@param data_nbytes Input byte size of data
@param data Input unsigned integer represented in big endian
@result r is initialized with the big unsigned number
@return 0 if no error, !=0 if the big number cannot be represented in the allocated cc_unit array.
@discussion The execution pattern of this function depends on both n and data_nbytes but not on data values except the handling
of the error case.
*/
CC_NONNULL((2, 4))
int ccn_read_uint(cc_size n, cc_unit *cc_counted_by(n) r, size_t data_nbytes, const uint8_t *cc_sized_by(data_nbytes) data);
/* r = (data, len) treated as a big endian byte array, return -1 if data
doesn't fit in r, return 0 otherwise.
ccn_read_uint strips leading zeroes and doesn't care about sign. */
#define ccn_read_int(n, r, data_size, data) ccn_read_uint(n, r, data_size, data)
/*!
@function ccn_write_uint_size
@abstract Compute the minimum size required to store an big integer
@param n Input size of the cc_unit array representing the input
@param s Input cc_unit array
@result Return value is the exact byte size of the big integer
@discussion
The execution flow is independent on the value of the big integer.
However, the use of the returned value may leak the position of the most significant byte
*/
CC_PURE CC_NONNULL((2)) size_t ccn_write_uint_size(cc_size n, const cc_unit *cc_counted_by(n) s);
/*!
@function ccn_write_uint
@abstract Serialize the big integer into a big endian byte buffer
@param n Input size of the cc_unit array representing the input
@param s Input cc_unit array
@param out_size Size of the output buffer
@param out Output byte array of size at least out_size
@discussion This function writes exactly
MIN(out_size,ccn_write_uint_size(n,s)) bytes truncating to keep the
most significant bytes when out_size<ccn_write_uint_size(n,s). The
execution flow of function is based on the position of the most
significant byte as well as input sizes.
*/
CC_NONNULL((2, 4))
void ccn_write_uint(cc_size n, const cc_unit *cc_counted_by(n) s, size_t out_size, void *cc_sized_by(out_size) out);
/*!
@function ccn_write_uint_padded_ct
@abstract Serialize the big integer into a big endian byte buffer
@param n Input size of the cc_unit array representing the input
@param s Input cc_unit array
@param out_size Size of the output buffer
@param out Output byte array of size at least out_size
@return number of leading zero bytes in case of success, a negative error value in case of failure
@result This function writes exactly out_size byte, padding with zeroes when necessary.
This function DOES NOT support truncation and returns an error if out_size < ccn_write_uint_size
@discussion The execution flow of function is independent on the value of the big integer
However, the processing of the return value by the caller may expose the position of
the most significant byte
*/
CC_NONNULL((2, 4))
int ccn_write_uint_padded_ct(cc_size n, const cc_unit *cc_sized_by(n) s, size_t out_size, uint8_t *cc_counted_by(out_size) out);
/*!
@function ccn_write_uint_padded
@abstract Serialize the big integer into a big endian byte buffer
Not recommended, for most cases ccn_write_uint_padded_ct is more appropriate
Sensitive big integers are exposed since the processing expose the position of the MS byte
@param n Input size of the cc_unit array representing the input
@param s Input cc_unit array
@param out_size Size of the output buffer
@param out Output byte array of size at least out_size
@return number of leading zero bytes
@result This function writes exactly out_size byte, padding with zeroes when necessary.
This function DOES support truncation when out_size<ccn_write_uint_size()
@discussion The execution flow of this function DEPENDS on the position of the most significant byte in
case truncation is required.
*/
CC_NONNULL((2, 4))
size_t ccn_write_uint_padded(cc_size n, const cc_unit *cc_counted_by(n) s, size_t out_size, uint8_t *cc_sized_by(out_size) out);
/* Return actual size in bytes needed to serialize s as int
(adding leading zero if high bit is set). */
CC_PURE CC_NONNULL((2))
size_t ccn_write_int_size(cc_size n, const cc_unit *cc_counted_by(n) s);
/* Serialize s, to out.
First byte of byte stream is the m.s. byte of s,
regardless of the size of cc_unit.
No assumption is made about the alignment of out.
The out_size argument should be the value returned from ccn_write_int_size,
and is also the exact number of bytes this function will write to out.
If out_size if less than the value returned by ccn_write_int_size, only the
first out_size non-zero most significant octets of s will be written. */
CC_NONNULL((2, 4))
void ccn_write_int(cc_size n, const cc_unit *cc_counted_by(n) s, size_t out_size, void *cc_sized_by(out_size) out);
CC_NONNULL((2))
void ccn_zero(cc_size n, cc_unit *cc_sized_by(n) r);
CC_NONNULL((2))
void ccn_seti(cc_size n, cc_unit *cc_counted_by(n) r, cc_unit v);
#define CC_SWAP_HOST_BIG_64(x) \
((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \
(((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \
(((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \
(((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \
(((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \
(((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \
(((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \
(((uint64_t)(x) & 0x00000000000000ffULL) << 56)))
#define CC_SWAP_HOST_BIG_32(x) \
((((x) & 0xff000000) >> 24) | \
(((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | \
(((x) & 0x000000ff) << 24))
#define CC_SWAP_HOST_BIG_16(x) \
((((x) & 0xff00) >> 8) | \
(((x) & 0x00ff) << 8))
/* This should probably move if we move ccn_swap out of line. */
#if CCN_UNIT_SIZE == 8
#define CC_UNIT_TO_BIG(x) CC_SWAP_HOST_BIG_64(x)
#elif CCN_UNIT_SIZE == 4
#define CC_UNIT_TO_BIG(x) CC_SWAP_HOST_BIG_32(x)
#else
#error Unsupported CCN_UNIT_SIZE
#endif
/*!
@function ccn_swap
@discussion Swaps r inplace from cc_unit vector byte order to big endian byte order (or back)
*/
CC_NONNULL((2))
void ccn_swap(cc_size n, cc_unit *cc_counted_by(n) r);
CC_NONNULL((2, 3, 4))
void ccn_xor(cc_size n, cc_unit *cc_counted_by(n) r, const cc_unit *cc_counted_by(n) s, const cc_unit *cc_counted_by(n) t);
/* Debugging */
CC_NONNULL((2))
void ccn_print(cc_size n, const cc_unit *cc_counted_by(n) s);
CC_NONNULL((3))
void ccn_lprint(cc_size n, const char *cc_cstring label, const cc_unit *cc_counted_by(n) s);
/* Forward declaration so we don't depend on ccrng.h. */
struct ccrng_state;
#define ccn_random(_n_,_r_,_ccrng_ctx_) \
ccrng_generate(_ccrng_ctx_, ccn_sizeof_n(_n_), (unsigned char *)_r_)
#endif /* _CORECRYPTO_CCN_H_ */

View file

@ -0,0 +1,74 @@
/* Copyright (c) (2010,2011,2012,2014,2015,2019) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCPAD_H_
#define _CORECRYPTO_CCPAD_H_
#include <corecrypto/ccmode.h>
// CTS1,2,3 are defined in Addendum to 800-38A,
// "Cipher Modes of Operation: Three Variants of Ciphertext Stealing for CBC Mode"
// CTS3 is also known as "CTS" in RFC3962
/* Contract is nbytes is at least 1 block + 1 byte. Also in is nbytes long out is nbytes long. */
size_t ccpad_cts1_decrypt(const struct ccmode_cbc *cbc, cccbc_ctx *ctx, cccbc_iv *iv,
size_t nbytes, const void *in, void *out);
/* Contract is nbytes is at least 1 block + 1 byte. Also in is nbytes long out is nbytes long. */
size_t ccpad_cts1_encrypt(const struct ccmode_cbc *cbc, cccbc_ctx *ctx, cccbc_iv *iv,
size_t nbytes, const void *in, void *out);
/* Contract is nbytes is at least 1 block + 1 byte. Also in is nbytes long out is nbytes long. */
size_t ccpad_cts2_decrypt(const struct ccmode_cbc *cbc, cccbc_ctx *ctx, cccbc_iv *iv,
size_t nbytes, const void *in, void *out);
/* Contract is nbytes is at least 1 block + 1 byte. Also in is nbytes long out is nbytes long. */
size_t ccpad_cts2_encrypt(const struct ccmode_cbc *cbc, cccbc_ctx *ctx, cccbc_iv *iv,
size_t nbytes, const void *in, void *out);
/* Contract is nbytes is at least 1 block + 1 byte. Also in is nbytes long out is nbytes long. */
size_t ccpad_cts3_decrypt(const struct ccmode_cbc *cbc, cccbc_ctx *ctx, cccbc_iv *iv,
size_t nbytes, const void *in, void *out);
/* Contract is nbytes is at least 1 block + 1 byte. Also in is nbytes long out is nbytes long. */
size_t ccpad_cts3_encrypt(const struct ccmode_cbc *cbc, cccbc_ctx *ctx, cccbc_iv *iv,
size_t nbytes, const void *in, void *out);
/* Contract is nbytes is non zero and a multiple of block_size. Furthermore in is nbytes long and out is nbytes long. Returns number of bytes written to out (technically we always write nbytes to out but the returned value is the number of bytes decrypted after removal of padding.
To be safe we remove the entire offending block if the pkcs7 padding checks failed. However we purposely don't report the failure to decode the padding since any use of this error leads to potential security exploits. So currently there is no way to distinguish between a full block of padding and bad padding.
*/
size_t ccpad_pkcs7_decrypt(const struct ccmode_cbc *cbc, cccbc_ctx *ctx, cccbc_iv *iv,
size_t nbytes, const void *in, void *out);
/* Contract is in is nbytes long. Writes (nbytes / block_size) + 1 times block_size to out. In other words, out must be nbytes rounded down to the closest multiple of block_size plus block_size bytes. */
size_t ccpad_pkcs7_encrypt(const struct ccmode_cbc *cbc, cccbc_ctx *ctx, cccbc_iv *iv,
size_t nbytes, const void *in, void *out);
/* Contract is 'don't break CommonCrypto functionality that allows PKCS7 padding with ECB mode'. This is basically the same routines above, without an IV, because calling
crypt with an IV makes ecb cry (and crash) */
size_t ccpad_pkcs7_ecb_decrypt(const struct ccmode_ecb *ecb, ccecb_ctx *ecb_key,
size_t nbytes, const void *in, void *out);
size_t ccpad_pkcs7_ecb_encrypt(const struct ccmode_ecb *ecb, ccecb_ctx *ctx,
size_t nbytes, const void *in, void *out);
/* Function common to ccpad_pkcs7_ecb_decrypt and ccpad_pkcs7_decrypt */
size_t ccpad_pkcs7_decode(const size_t block_size, const uint8_t* last_block);
/* Contract is nbytes is at least 1 block + 1 byte. Also in is nbytes long out is nbytes long. */
size_t ccpad_xts_decrypt(const struct ccmode_xts *xts, ccxts_ctx *ctx, ccxts_tweak *tweak,
size_t nbytes, const void *in, void *out);
/* Contract is nbytes is at least 1 block + 1 byte. Also in is nbytes long out is nbytes long. */
void ccpad_xts_encrypt(const struct ccmode_xts *xts, ccxts_ctx *ctx, ccxts_tweak *tweak,
size_t nbytes, const void *in, void *out);
#endif /* _CORECRYPTO_CCPAD_H_ */

View file

@ -0,0 +1,76 @@
/* Copyright (c) (2010-2020,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCRNG_H_
#define _CORECRYPTO_CCRNG_H_
#include <corecrypto/cc.h>
#define CCRNG_STATE_COMMON \
int (*CC_SPTR(ccrng_state, generate))(struct ccrng_state *rng, size_t outlen, void *out);
/*!
@type struct ccrng_state
@abstract Default state structure. Do not instantiate. ccrng() returns a reference to this structure
*/
struct ccrng_state {
CCRNG_STATE_COMMON
};
/*!
@function ccrng
@abstract Get a handle to a secure RNG
@param error A pointer to set in case of error; may be null
@result A handle to a secure RNG, or null if one cannot be initialized successfully
@discussion
This function returns a pointer to the most appropriate RNG for the
environment. This may be a TRNG if one is available. Otherwise, it is
a PRNG offering several features:
- Good performance
- FIPS Compliant: NIST SP800-90A + FIPS 140-2
- Seeded from the appropriate entropy source for the platform
- Provides at least 128-bit security
- Backtracing resistance
- Prediction break (after reseed)
*/
struct ccrng_state *ccrng(int *error);
/*!
@function ccrng_generate
@abstract Generate `outlen` bytes of output, stored in `out`, using ccrng_state `rng`.
@param rng `struct ccrng_state` representing the state of the RNG.
@param outlen Amount of random bytes to generate.
@param out Pointer to memory where random bytes are stored, of size at least `outlen`.
@result 0 on success and nonzero on failure.
*/
#define ccrng_generate(rng, outlen, out) \
((rng)->generate((struct ccrng_state *)(rng), (outlen), (out)))
#if !CC_EXCLAVEKIT
/*!
@function ccrng_uniform
@abstract Generate a random value in @p [0, bound).
@param rng The state of the RNG.
@param bound The exclusive upper bound on the output.
@param rand A pointer to a single @p uint64_t to store the result.
@result Returns zero iff the operation is successful.
*/
int ccrng_uniform(struct ccrng_state *rng, uint64_t bound, uint64_t *rand);
#endif
#endif /* _CORECRYPTO_CCRNG_H_ */

View file

@ -0,0 +1,74 @@
/* Copyright (c) (2021,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCRNG_CRYPTO_H_
#define _CORECRYPTO_CCRNG_CRYPTO_H_
#include <corecrypto/ccrng.h>
#include <corecrypto/ccrng_schedule.h>
#include <corecrypto/ccentropy.h>
#include "cc_lock.h"
// This is a framework for a cryptographically-secure RNG. It is
// configurable in many aspects, including:
//
// - DRBG implementation
// - Entropy source
// - Reseed schedule
// - Locks (optional)
// - Request chunking
// - Output caching
#define CCRNG_CRYPTO_SEED_MAX_NBYTES ((size_t)64)
typedef struct ccrng_crypto_ctx {
CCRNG_STATE_COMMON
ccentropy_ctx_t *entropy_ctx;
ccrng_schedule_ctx_t *schedule_ctx;
cc_lock_ctx_t *lock_ctx;
const struct ccdrbg_info *drbg_info;
struct ccdrbg_state *drbg_ctx;
size_t generate_chunk_nbytes;
size_t seed_nbytes;
size_t cache_nbytes;
uint8_t *cache;
size_t cache_pos;
} ccrng_crypto_ctx_t;
int
ccrng_crypto_init(ccrng_crypto_ctx_t *ctx,
ccentropy_ctx_t *entropy_ctx,
ccrng_schedule_ctx_t *schedule_ctx,
cc_lock_ctx_t *lock_ctx,
const struct ccdrbg_info *drbg_info,
struct ccdrbg_state *drbg_ctx,
size_t generate_chunk_nbytes,
size_t seed_nbytes,
size_t cache_nbytes,
void *cache);
int
ccrng_crypto_generate(ccrng_crypto_ctx_t *ctx,
size_t nbytes,
void *rand);
int
ccrng_crypto_reseed(ccrng_crypto_ctx_t *ctx,
size_t seed_nbytes,
const void *seed,
size_t nonce_nbytes,
const void *nonce);
#endif /* _CORECRYPTO_CCRNG_CRYPTO_H_ */

View file

@ -0,0 +1,198 @@
/* Copyright (c) (2018-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCRNG_FORTUNA_H_
#define _CORECRYPTO_CCRNG_FORTUNA_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccrng.h>
#include "cc_lock.h"
// This is a Fortuna-inspired PRNG. While it differs from Fortuna in
// many minor details, the biggest difference is its support for
// multiple independent output generators. This is to make it suitable
// for use in concurrent environments.
//
// This PRNG targets a 256-bit security level.
//
// First, the user should call ccrng_fortuna_init. The user must
// specify the maximum number of output generators that might be
// needed. (Typically, users should align this argument with the
// number of available CPUs.)
//
// The user must also provide a read-only handle to an entropy
// source. This is a fixed-size buffer that will receive entropy
// updates out of band from the PRNG (e.g. in an interrupt
// handler). The PRNG will consume entropy from this buffer according
// to an internal schedule driven by calls to ccrng_fortuna_refresh
// (see below).
//
// The user should call ccrng_fortuna_initgen for as many output
// generators as are needed. The numeric argument is an identifier to
// be reused during calls to ccrng_fortuna_generate (see below) and
// must be less than the maximum number of generators specified to
// ccrng_fortuna_init.
//
// After initialization, the user is free to call
// ccrng_fortuna_generate to generate random bytes. The user must
// specify the generator in this call using a numeric identifier
// passed in the call to ccrng_fortuna_initgen.
//
// Output generation is limited to 256 bytes per request. Users should
// make multiple requests if more output is needed.
//
// The user is expected to call ccrng_fortuna_refresh regularly. This
// function consumes entropy and mixes it into the output generators
// according to an internal schedule.
//
// This implementation is thread-safe. Internally, a set of mutexes
// guard access to internal state. Most functions rely on a single
// mutex to protect shared state. The main exception is the
// ccrng_fortuna_generate function, which uses a per-generator mutex
// to allow concurrent output generation on different threads.
//
// Another important exception is ccrng_fortuna_refresh. While this
// function relies on the shared mutex, it returns immediately if it
// cannot acquire it.
//
// The PRNG also supports user-initiated reseeds. This is to support a
// user-writable random device.
//
// This PRNG supports reseeds concurrent with output generation,
// i.e. it is safe to call ccrng_fortuna_reseed or
// ccrng_fortuna_refresh while another thread is calling
// ccrng_fortuna_generate.
#define CCRNG_FORTUNA_NPOOLS 32
#define CCRNG_FORTUNA_SEED_NBYTES 32
#define CCRNG_FORTUNA_POOL_NBYTES 32
#define CCRNG_FORTUNA_KEY_NBYTES 32
struct ccrng_fortuna_pool_ctx {
uint8_t data[CCRNG_FORTUNA_POOL_NBYTES];
// The number of samples currently resident in the pool
uint64_t nsamples;
// The number of times this pool has been drained in a reseed
uint64_t ndrains;
// The maximum number of samples this pool has held at any one time
uint64_t nsamples_max;
};
struct ccrng_fortuna_sched_ctx {
// A counter governing the set of entropy pools to drain
uint64_t reseed_sched;
// An index used to add entropy to pools in a round-robin style
unsigned pool_idx;
};
// A function pointer to fill an entropy buffer. It should return some
// estimate of entropy (e.g. the number of timing samples resident in
// the buffer). The implementation may return zero if no entropy is
// available. The implementation should return negative in case of an
// error (e.g. a failure in continuous health tests).
//
// The caller should set entropy_nbytes to the maximum size of the
// input buffer, and the implementation should set it to the number of
// bytes it has initialized. The third argument is arbitrary state the
// implementation provides and receives back on each call.
typedef int32_t (*ccrng_fortuna_getentropy)(size_t *entropy_nbytes,
void *entropy,
void *arg);
struct ccrng_fortuna_ctx {
CCRNG_STATE_COMMON
// The root secret of the PRNG
uint8_t key[CCRNG_FORTUNA_KEY_NBYTES];
// A counter used in CTR mode (with the root secret)
uint8_t ctr[16];
// State used to schedule entropy consumption and reseeds
struct ccrng_fortuna_sched_ctx sched;
// A mutex governing access to shared state
cc_lock_ctx_t lock;
// A set of entropy pools
struct ccrng_fortuna_pool_ctx pools[CCRNG_FORTUNA_NPOOLS];
// A function pointer to get entropy
CC_SPTR(ccrng_fortuna_ctx, ccrng_fortuna_getentropy) getentropy;
// An arbitrary piece of state to be provided to the entropy function
void *getentropy_arg;
// A flag describing whether the instance has been seeded with
// sufficient entropy. This flag is set when a set of pools
// containing a minimum threshold of entropy inputs is
// drained. The PRNG will not generate output until this flag is
// set. This flag is reset if the entropy source signals a
// failure.
bool seeded;
// The number of scheduled reseeds
uint64_t nreseeds;
// The maximum number of samples included in any one scheduler reseed
uint64_t schedreseed_nsamples_max;
// The maximum number of samples included in any one entropy input
uint64_t addentropy_nsamples_max;
};
/*
@function ccrng_fortuna_init
@abstract Initialize a kernel PRNG context.
@param ctx Context for this instance
@param getentropy A function pointer to fill an entropy buffer
@param getentropy_arg State provided to the entropy function
@discussion @p max_ngens should be set based on an upper bound of CPUs available on the device. See the @p ccrng_fortuna_getentropy type definition for discussion on its semantics.
*/
void ccrng_fortuna_init(struct ccrng_fortuna_ctx *ctx,
ccrng_fortuna_getentropy getentropy,
void *getentropy_arg);
/*
@function ccrng_fortuna_refresh
@abstract Consume entropy and reseed according to an internal schedule.
@param ctx Context for this instance
@return True if a reseed occurred, false otherwise.
@discussion This function should be called on a regular basis. (For example, it is reasonable to call this inline before a call to @p ccrng_fortuna_generate.) This function will not necessarily consume entropy or reseed the internal state on any given invocation. To force an immediate reseed, call @p ccrng_fortuna_reseed.
*/
bool ccrng_fortuna_refresh(struct ccrng_fortuna_ctx *ctx);
#define CCRNG_FORTUNA_GENERATE_MAX_NBYTES 256
/*
@function ccrng_fortuna_generate
@abstract Generate random values for use in applications.
@param ctx Context for this instance
@param nbytes Length of the desired output in bytes
@param out Pointer to the output buffer
@return 0 on success, negative otherwise.
@discussion @p gen_idx must be a previous argument to @p ccrng_fortuna_initgen. @p nbytes must be less than or equal to @p CCRNG_FORTUNA_GENERATE_MAX_NBYTES. (Callers may invoke this function in a loop to generate larger outputs.) This function will abort if these contracts are violated.
*/
int ccrng_fortuna_generate(struct ccrng_fortuna_ctx *ctx, size_t nbytes, void *out);
#endif /* _CORECRYPTO_CCRNG_FORTUNA_H_ */

View file

@ -0,0 +1,114 @@
/* Copyright (c) (2021,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCRNG_SCHEDULE_H_
#define _CORECRYPTO_CCRNG_SCHEDULE_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccdrbg.h>
#include <stdatomic.h>
// Depending on the environment and platform APIs available, different
// RNGs will use different reseed strategies. For example, an RNG that
// can communicate with its entropy source might check a flag set by
// the latter when entropy is available. In another case, the RNG
// might poll its entropy source on a time interval. In some cases,
// the RNG might always (or never) want to try to reseed.
//
// This module provides a common interface for such reseed
// schedules. It is intended for use as a component by RNG
// implementations.
typedef enum {
CCRNG_SCHEDULE_CONTINUE = 1,
CCRNG_SCHEDULE_TRY_RESEED = 2,
CCRNG_SCHEDULE_MUST_RESEED = 3,
} ccrng_schedule_action_t;
typedef struct ccrng_schedule_ctx ccrng_schedule_ctx_t;
// The schedule interface provides two function pointers: one to check
// the schedule and one to notify the schedule of a successful reseed.
typedef struct ccrng_schedule_info {
ccrng_schedule_action_t (*read)(ccrng_schedule_ctx_t *ctx);
void (*notify_reseed)(ccrng_schedule_ctx_t *ctx);
} ccrng_schedule_info_t;
struct ccrng_schedule_ctx {
const ccrng_schedule_info_t *info;
bool must_reseed;
};
ccrng_schedule_action_t ccrng_schedule_read(ccrng_schedule_ctx_t *ctx);
void ccrng_schedule_notify_reseed(ccrng_schedule_ctx_t *ctx);
// This is a concrete schedule implementation where the state of the
// entropy source is communicated via a flag. The entropy source can
// set the flag with ccrng_schedule_atomic_flag_set to indicate
// entropy is available. The flag is cleared automatically on read and
// reset if the reseed fails.
typedef struct ccrng_schedule_atomic_flag_ctx {
ccrng_schedule_ctx_t schedule_ctx;
_Atomic ccrng_schedule_action_t flag;
} ccrng_schedule_atomic_flag_ctx_t;
void ccrng_schedule_atomic_flag_init(ccrng_schedule_atomic_flag_ctx_t *ctx);
void ccrng_schedule_atomic_flag_set(ccrng_schedule_atomic_flag_ctx_t *ctx);
// This is a concrete schedule implementation that simply always
// returns a constant action.
typedef struct ccrng_schedule_constant_ctx {
ccrng_schedule_ctx_t schedule_ctx;
ccrng_schedule_action_t action;
} ccrng_schedule_constant_ctx_t;
void ccrng_schedule_constant_init(ccrng_schedule_constant_ctx_t *ctx,
ccrng_schedule_action_t action);
// This is a concrete schedule implementation that returns "must
// reseed" over a given interval of time.
typedef struct ccrng_schedule_timer_ctx {
ccrng_schedule_ctx_t schedule_ctx;
uint64_t (*get_time)(void);
uint64_t reseed_interval;
uint64_t last_reseed_time;
} ccrng_schedule_timer_ctx_t;
void ccrng_schedule_timer_init(ccrng_schedule_timer_ctx_t *ctx,
uint64_t (*get_time)(void),
uint64_t reseed_interval);
// This is a concrete schedule implementation that combines the
// results of two constituent sub-schedules. Specifically, it returns
// the more "urgent" recommendation between the two.
typedef struct ccrng_schedule_tree_ctx {
ccrng_schedule_ctx_t schedule_ctx;
ccrng_schedule_ctx_t *left;
ccrng_schedule_ctx_t *right;
} ccrng_schedule_tree_ctx_t;
void ccrng_schedule_tree_init(ccrng_schedule_tree_ctx_t *ctx,
ccrng_schedule_ctx_t *left,
ccrng_schedule_ctx_t *right);
typedef struct ccrng_schedule_drbg_ctx {
ccrng_schedule_ctx_t schedule_ctx;
const struct ccdrbg_info *drbg_info;
struct ccdrbg_state *drbg_ctx;
} ccrng_schedule_drbg_ctx_t;
void ccrng_schedule_drbg_init(ccrng_schedule_drbg_ctx_t *ctx,
const struct ccdrbg_info *drbg_info,
struct ccdrbg_state *drbg_ctx);
#endif /* _CORECRYPTO_CCRNG_SCHEDULE_H_ */

View file

@ -0,0 +1,873 @@
/* Copyright (c) (2010-2012,2014-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCRSA_H_
#define _CORECRYPTO_CCRSA_H_
#include <corecrypto/cc.h>
#include <corecrypto/ccdigest.h>
#include <corecrypto/ccrng.h>
#include <corecrypto/cczp.h>
#include <corecrypto/cc_fault_canary.h>
CC_PTRCHECK_CAPABLE_HEADER()
// Apple does not generate keys of greater than 4096 bits
// This limit is relaxed to accommodate potential third-party consumers
#define CCRSA_KEYGEN_MAX_NBITS 8192
struct ccrsa_full_ctx {
__CCZP_ELEMENTS_DEFINITIONS(pb_)
} CC_ALIGNED(CCN_UNIT_SIZE);
struct ccrsa_pub_ctx {
__CCZP_ELEMENTS_DEFINITIONS(pb_)
} CC_ALIGNED(CCN_UNIT_SIZE);
typedef struct ccrsa_full_ctx* ccrsa_full_ctx_t;
typedef struct ccrsa_pub_ctx* ccrsa_pub_ctx_t;
/*
struct ccrsa_pub_ctx {
cczp zm;
cc_unit m[n];
cc_unit m0inv;
cc_unit mr2[n];
cc_unit e[n];
}
struct ccrsa_priv_ctx {
cc_unit d[n]; // e^(-1) mod lcm(p-1, q-1)
cczp zp;
cc_unit p[n/2+1];
cc_unit p0inv;
cc_unit pr2[n/2+1];
cczp zq;
cc_unit q[n/2+1];
cc_unit q0inv;
cc_unit qr2[n/2+1];
cc_unit dp[n/2+1]; // d mod (p-1)
cc_unit dq[n/2+1]; // d mod (q-1)
cc_unit qinv[n/2+1]; // q^(-1) mod p
}
struct ccrsa_full_ctx {
struct ccrsa_pub_ctx;
struct ccrsa_priv_ctx;
}
*/
// Compute the internal structure size in bytes based on key (i.e. modulus) byte size.
#define ccrsa_pub_ctx_size(_nbytes_) (sizeof(struct cczp) + CCN_UNIT_SIZE + 3 * ccn_sizeof_size(_nbytes_))
#define ccrsa_priv_ctx_size(_nbytes_) (ccn_sizeof_size(_nbytes_) + (sizeof(struct cczp) + CCN_UNIT_SIZE) * 2 + 7 * ccn_sizeof_n(ccn_nof_size(_nbytes_) / 2 + 1))
#define ccrsa_full_ctx_size(_nbytes_) (ccrsa_pub_ctx_size(_nbytes_) + ccrsa_priv_ctx_size(_nbytes_))
#define ccrsa_pub_ctx_ws(_n_) ccn_nof_size(ccrsa_pub_ctx_size(ccn_sizeof_n(_n_)))
#define ccrsa_full_ctx_ws(_n_) ccn_nof_size(ccrsa_full_ctx_size(ccn_sizeof_n(_n_)))
// Declare structure based on key byte size.
#define ccrsa_full_ctx_decl(_nbytes_, _name_) cc_ctx_decl(struct ccrsa_full_ctx, ccrsa_full_ctx_size(_nbytes_), _name_)
#define ccrsa_full_ctx_clear(_nbytes_, _name_) cc_clear(ccrsa_full_ctx_size(_nbytes_), _name_)
#define ccrsa_pub_ctx_decl(_nbytes_, _name_) cc_ctx_decl(struct ccrsa_pub_ctx, ccrsa_pub_ctx_size(_nbytes_), _name_)
#define ccrsa_pub_ctx_clear(_nbytes_, _name_) cc_clear(ccrsa_pub_ctx_size(_nbytes_), _name_)
// Declare structure based on key bit size.
#define ccrsa_full_ctx_decl_nbits(_nbits_, _name_) cc_ctx_decl(struct ccrsa_full_ctx, ccrsa_full_ctx_size(ccn_sizeof(_nbits_)), _name_)
#define ccrsa_full_ctx_clear_nbits(_nbits_, _name_) cc_clear(ccrsa_full_ctx_size(ccn_sizeof(_nbits_)), _name_)
#define ccrsa_pub_ctx_decl_nbits(_nbits_, _name_) cc_ctx_decl(struct ccrsa_pub_ctx, ccrsa_pub_ctx_size(ccn_sizeof(_nbits_)), _name_)
#define ccrsa_pub_ctx_clear_nbits(_nbits_, _name_) cc_clear(ccrsa_pub_ctx_size(ccn_sizeof(_nbits_)), _name_)
// Declare structure based number of cc_units. Not a typical use case. Size depends on processor.
#define ccrsa_full_ctx_decl_n(_nunits_, _name_) cc_ctx_decl(struct ccrsa_full_ctx, ccrsa_full_ctx_size(ccn_sizeof_n(_nunits_)), _name_)
#define ccrsa_full_ctx_clear_n(_nunits_, _name_) cc_clear(ccrsa_full_ctx_size(ccn_sizeof_n(_nunits_)), _name_)
#define ccrsa_pub_ctx_decl_n(_nunits_, _name_) cc_ctx_decl(struct ccrsa_pub_ctx, ccrsa_pub_ctx_size(ccn_sizeof_n(_nunits_)), _name_)
#define ccrsa_pub_ctx_clear_n(_nunits_, _name_) cc_clear(ccrsa_pub_ctx_size(ccn_sizeof_n(_nunits_)), _name_)
// Accessors to ccrsa full and public key fields. */
// The offsets are computed using pb_ccn. If any object other than ccrsa_full_ctx_t
// or ccrsa_pub_ctx_t is passed to the macros, compiler error is generated.
#define ccrsa_ctx_zm(_ctx_) ((struct cczp* cc_single)(_ctx_))
#define ccrsa_ctx_n(_ctx_) (ccrsa_ctx_zm(_ctx_)->n)
#define ccrsa_ctx_m(_ctx_) ((cc_unit *)cc_unsafe_forge_bidi_indexable((_ctx_)->pb_ccn, ccn_sizeof_n(ccrsa_ctx_n(_ctx_))))
// Forge a bixi indexable at (_ctx_->pb_cnn + _offset_), of size in bytes _nbytes_.
#define ccrsa_unsafe_forge_bidi_indexable(_ctx_, _nbytes_, _offset_) ((cc_unit *)cc_unsafe_forge_bidi_indexable((cc_unit *)cc_unsafe_forge_bidi_indexable((_ctx_)->pb_ccn, _nbytes_ + ccn_sizeof_n(_offset_)) + _offset_, _nbytes_))
#define ccrsa_ctx_e(_ctx_) ccrsa_unsafe_forge_bidi_indexable(_ctx_, ccn_sizeof_n(ccrsa_ctx_n(_ctx_)), 2 * ccrsa_ctx_n(_ctx_) + 1)
#define ccrsa_ctx_d(_ctx_) ccrsa_unsafe_forge_bidi_indexable(_ctx_, ccn_sizeof_n(ccrsa_ctx_n(_ctx_)), 3 * ccrsa_ctx_n(_ctx_) + 1)
// accessors to ccrsa private key fields
#define ccrsa_ctx_private_zq(FK) ((cczp_t)(ccrsa_ctx_private_zp(FK)->ccn + 2 * ccrsa_ctx_private_zp(FK)->n + 1))
#define ccrsa_ctx_private_dp(FK) (ccrsa_ctx_private_zq(FK)->ccn + 2 * ccrsa_ctx_private_zp(FK)->n + 1)
#define ccrsa_ctx_private_dq(FK) (ccrsa_ctx_private_dp(FK) + ccrsa_ctx_private_zp(FK)->n)
#define ccrsa_ctx_private_qinv(FK) (ccrsa_ctx_private_dq(FK) + ccrsa_ctx_private_zp(FK)->n)
cczp_t ccrsa_ctx_private_zp(ccrsa_full_ctx_t fk);
/*!
@function ccrsa_ctx_public
@abstract gets the public key from full key
@param fk RSA full key
@result Returns RSA public ker
*/
ccrsa_pub_ctx_t ccrsa_ctx_public(ccrsa_full_ctx_t fk);
/*!
@function ccrsa_pubkeylength
@abstract Compute the actual bit length of the RSA key (bit length of the modulus)
@param pubk An initialized RSA public key
@result bit length of the RSA key
*/
CC_NONNULL_ALL
size_t ccrsa_pubkeylength(ccrsa_pub_ctx_t pubk);
/* PKCS1 pad_markers */
#define CCRSA_PKCS1_PAD_SIGN 1
#define CCRSA_PKCS1_PAD_ENCRYPT 2
/*!
@function ccrsa_init_pub
@abstract Initialize an RSA public key structure based on modulus and exponent. Values are copied into the structure.
@param pubk allocated public key structure (see requirements below)
@param modulus cc_unit array of the modulus
@param exponent cc_unit array of the exponent
@result CCERR_OK if no error
@discussion ccrsa_ctx_n(pubk) must have been initialized based on the modulus size, typically using ccn_nof_size(mod_nbytes).
The public key structure pubk is typically allocated with ccrsa_pub_ctx_decl(mod_nbytes, pubk);
*/
CC_NONNULL_ALL
int ccrsa_init_pub(ccrsa_pub_ctx_t pubk, const cc_unit *modulus,
const cc_unit *exponent);
/*! @function ccrsa_make_priv
@abstract Initializes an RSA public and private key given the public
exponent e and prime factors p and q.
@param full_ctx Initialized context with ccrsa_ctx_n(full_ctx) set to 2*ccn_nof_size(p_nbytes)
@param e_nbytes Number of bytes of public exponent e.
@param e_bytes Public exponent e in Big Endian.
@param p_nbytes Number of bytes of prime factor p.
@param p_bytes Prime factor p in Big Endian.
@param q_nbytes Number of bytes of prime factor q.
@param q_bytes Prime factor q in Big Endian.
@return 0 iff successful.
@discussion ccrsa_ctx_n(full_ctx) must already be set to 2*ccn_nof_size(p_mbytes), with the expectation that p_nbytes>q_nbytes.
e is the public exponent, and e_nbytes<= 2*p_nbytes.
The output is a fully formed RSA context with N=pq, d=e^{-1} mod lambda(N), and appropriate inverses of different associated values precomputed
to speed computation.
*/
int ccrsa_make_priv(ccrsa_full_ctx_t full_ctx,
size_t e_nbytes, const uint8_t *cc_counted_by(e_nbytes) e_bytes,
size_t p_nbytes, const uint8_t *cc_counted_by(p_nbytes) p_bytes,
size_t q_nbytes, const uint8_t *cc_counted_by(q_nbytes) q_bytes);
/*! @function ccrsa_recover_priv
@abstract Initializes an RSA public and private key given the modulus m,
the public exponent e and the private exponent d.
@discussion Follows the algorithm described by
NIST SP 800-56B, Appendix C, "Prime Factory Recovery".
@param full_ctx Initialized context with ccrsa_ctx_n(full_ctx) set to ccn_nof_size(m_nbytes)
@param m_nbytes Number of bytes of modulus m.
@param m_bytes Modulus m in Big Endian.
@param e_nbytes Number of bytes of public exponent e.
@param e_bytes Public exponent e in Big Endian.
@param d_nbytes Number of bytes of private exponent d.
@param d_bytes Private exponent d in Big Endian.
@param rng RNG instance.
@return 0 iff successful.
*/
int ccrsa_recover_priv(ccrsa_full_ctx_t full_ctx,
size_t m_nbytes, const uint8_t *cc_counted_by(m_nbytes) m_bytes,
size_t e_nbytes, const uint8_t *cc_counted_by(e_nbytes) e_bytes,
size_t d_nbytes, const uint8_t *cc_counted_by(d_nbytes) d_bytes,
struct ccrng_state *rng);
/*!
@function ccrsa_make_pub
@abstract Initialize public key based on modulus and public exponent as big endian byte arrays;
@param pubk allocated public key structure (see requirements below)
@param exp_nbytes Number of bytes in big endian exponent.
@param exp Pointer to big endian exponent e (may have leading 0's).
@param mod_nbytes Number of bytes in big endian modulus.
@param mod Pointer to big endian to rsa modulus N.
@result 0 iff successful.
@discussion ccrsa_ctx_n(pubk) must have been initialized based on the modulus size, typically using ccn_nof_size(mod_nbytes).
The public key structure pubk is typically allocated with ccrsa_pub_ctx_decl(mod_nbytes, pubk);
*/
CC_NONNULL((1, 3, 5))
int ccrsa_make_pub(ccrsa_pub_ctx_t pubk,
size_t exp_nbytes, const uint8_t *cc_counted_by(exp_nbytes) exp,
size_t mod_nbytes, const uint8_t *cc_counted_by(mod_nbytes) mod);
/*!
@function ccrsa_pub_crypt
@abstract Perform an RSA public key operation: (in)^e mod m
@param key initialized public key defining e and m
@param out result of the operation, at least ccrsa_key_n(key) cc_units must have been allocated
@param in base of the exponentiation, of size ccrsa_key_n(key)
@result CCERR_OK if no error
@discussion Input to this function must not be secrets as the execution flow may expose their values
Clients can use ccn_read_uint() to convert bytes to cc_units to use for this API.
*/
CC_NONNULL((1, 2, 3))
int ccrsa_pub_crypt(ccrsa_pub_ctx_t key, cc_unit *cc_unsafe_indexable out, const cc_unit *cc_unsafe_indexable in);
/*!
@function ccrsa_generate_key
@abstract Generate a nbit RSA key pair.
@param nbits Bit size requested for the key
@param fk Allocated context where the generated key will be stored
@param e_nbytes Byte size of the input public exponent
@param e_bytes Input public exponent in big endian. Recommend value is {0x01, 0x00, 0x01}
@param rng Random Number generator used.
@result CCERR_OK if no error
@discussion
fk should be allocated using ccrsa_full_ctx_decl_nbits(nbits, fk).
The unsigned big endian byte array exponent e of length e_size is used as the exponent. It's an error to call this function with an exponent larger than nbits
*/
CC_NONNULL_ALL
int ccrsa_generate_key(size_t nbits, ccrsa_full_ctx_t fk,
size_t e_nbytes, const void *cc_sized_by(e_nbytes) e_bytes, struct ccrng_state *rng) CC_WARN_RESULT;
/*!
@function ccrsa_generate_key_deterministic
@abstract Generate a deterministic nbit RSA key pair.
@param nbits Bit size requested for the key.
@param fk Allocated context where the generated key will be stored.
@param e_nbytes Byte length of public exponent.
@param e Public exponent in big endian. Recommend value is {0x01, 0x00, 0x01}.
@param entropy_nbytes Byte length of entropy.
@param entropy Entropy, initial DRBG seed.
@param nonce_nbytes Byte length of nonce.
@param nonce Unique value combined with the entropy/seed.
@param flags Bitmap for options.
(Only CCRSA_GENKEY_DETERMINISTIC_LEGACY currently supported.)
@param rng Random Number generator for primality testing.
@result CCERR_OK if no error
@discussion
fk should be allocated using ccrsa_full_ctx_decl_nbits(nbits, fk).
The unsigned big endian byte array exponent e of length e_size is used as the exponent. It's an error to call this function with an exponent larger than nbits
*/
CC_NONNULL((2, 4, 6, 10))
int ccrsa_generate_key_deterministic(size_t nbits, ccrsa_full_ctx_t fk,
size_t e_nbytes, const uint8_t *cc_sized_by(e_nbytes) e,
size_t entropy_nbytes, const uint8_t *cc_sized_by(entropy_nbytes) entropy,
size_t nonce_nbytes, const uint8_t *cc_sized_by(nonce_nbytes) nonce,
uint32_t flags,
struct ccrng_state *rng);
#define CCRSA_GENKEY_DETERMINISTIC_LEGACY 0b1
/*!
@function ccrsa_generate_fips186_key
@abstract Generate a nbit RSA key pair in conformance with FIPS186-4 standard.
@param nbits Bit size requested for the key
@param fk Allocated context where the generated key will be stored
@param e_nbytes Byte size of the input public exponent
@param e_bytes Input public exponent in big endian. Recommend value is {0x01, 0x00, 0x01}
@param rng Random Number generator used for p and q
@param rng_mr Random Number generator only used for the primality check
@result CCERR_OK if no error
@discussion
fk should be allocated using ccrsa_full_ctx_decl_nbits(nbits, fk).
rng and rng_mr shoud be set to the same value. The distinction is only relevant for testing
*/
CC_NONNULL_ALL int
ccrsa_generate_fips186_key(size_t nbits, ccrsa_full_ctx_t fk,
size_t e_nbytes, const void *cc_sized_by(e_nbytes) e_bytes,
struct ccrng_state *rng, struct ccrng_state *rng_mr) CC_WARN_RESULT;
/*
Signing and Verification algorithms
*/
/*!
@function ccrsa_sign_pss
@brief ccrsa_sign_pss() generates RSASSA-PSS signature in PKCS1-V2 format given an input digest
@param key The RSA key
@param hashAlgorithm The hash algorithm used to generate mHash from the original message. It is also used inside the PSS encoding function.
@param MgfHashAlgorithm The hash algorithm for thr mask generation function
@param rng Random number geberator to generate salt in PSS encoding
@param salt_nbytes Intended length of the salt
@param digest_nbytes Length of message hash . Must be equal to hashAlgorithm->output_size
@param digest The input that needs to be signed. This is the hash of message M with length of hLen
@param sig_nbytes The length of generated signature in bytes, which equals the size of the RSA modulus.
@param sig The signature output
@return 0:ok, non-zero:error
@discussion
note that in RSASSA-PSS, salt length is part of the signature as specified in ASN1
RSASSA-PSS-params ::= SEQUENCE {
hashAlgorithm [0] HashAlgorithm DEFAULT sha1,
maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
saltLength [2] INTEGER DEFAULT 20,
trailerField [3] TrailerField DEFAULT trailerFieldBC
If nlen = 1024 bits (i.e., 128 bytes), and the output length of the approved hash function output block is 512 bits (i.e., 64 bytes), then the length (in bytes) of the salt (sLen) shall satisfy 0 sLen hLen 2,
Otherwise, the length (in bytes) of the salt (sLen) shall satisfy 0 sLen hLen, where hLen is the length of the hash function output block (in bytes).
*/
CC_NONNULL((1, 2, 3, 5, 7, 8, 9))
int ccrsa_sign_pss(ccrsa_full_ctx_t key,
const struct ccdigest_info* hashAlgorithm, const struct ccdigest_info* MgfHashAlgorithm,
size_t salt_nbytes, struct ccrng_state *rng,
size_t digest_nbytes, const uint8_t *cc_counted_by(digest_nbytes) digest,
size_t *sig_nbytes, uint8_t *cc_unsafe_indexable sig);
/*!
@function ccrsa_sign_pss_msg
@brief ccrsa_sign_pss_msg() generates a RSASSA-PSS signature in PKCS1-V2 format given an input message
@param key The RSA key
@param hashAlgorithm The hash algorithm used to generate mHash from the input message. It is also used inside the PSS encoding function.
@param MgfHashAlgorithm The hash algorithm for thr mask generation function
@param rng Random number generator to generate salt in PSS encoding
@param salt_nbytes Intended length of the salt
@param msg_nbytes Length of message.
@param msg The input that needs to be signed. This will be hashed using `hashAlgorithm`
@param sig_nbytes The length of generated signature in bytes, which equals the size of the RSA modulus.
@param sig The signature output
@return 0:ok, non-zero:error
@discussion
note that in RSASSA-PSS, salt length is part of the signature as specified in ASN1
RSASSA-PSS-params ::= SEQUENCE {
hashAlgorithm [0] HashAlgorithm DEFAULT sha1,
maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1,
saltLength [2] INTEGER DEFAULT 20,
trailerField [3] TrailerField DEFAULT trailerFieldBC
If nlen = 1024 bits (i.e., 128 bytes), and the output length of the approved hash function output block is 512 bits (i.e., 64 bytes), then the length (in bytes) of the salt (sLen) shall satisfy 0 sLen hLen 2,
Otherwise, the length (in bytes) of the salt (sLen) shall satisfy 0 sLen hLen, where hLen is the length of the hash function output block (in bytes).
*/
CC_NONNULL((1, 2, 3, 5, 7, 8, 9))
int ccrsa_sign_pss_msg(ccrsa_full_ctx_t key,
const struct ccdigest_info* hashAlgorithm, const struct ccdigest_info* MgfHashAlgorithm,
size_t salt_nbytes, struct ccrng_state *rng,
size_t msg_nbytes, const uint8_t *cc_counted_by(msg_nbytes) msg,
size_t *sig_nbytes, uint8_t *cc_unsafe_indexable sig);
/*!
@function ccrsa_verify_pss_digest
@brief ccrsa_verify_pss_digest() verifies RSASSA-PSS signature in PKCS1-V2 format, given the digest
@param key The RSA public key
@param di The hash algorithm used to generate the hash of the message.
@param mgfdi The hash algorithm for the mask generation function
@param digest_nbytes Length of digest. Must be equal to di->output_size
@param digest The signed message hash
@param sig_nbytes The length of generated signature in bytes, which equals the size of the RSA modulus.
@param sig The signature to verify
@param salt_nbytes Length of the salt as used during signature generation.
@param fault_canary_out OPTIONAL cc_fault_canary_t (see discussion)
@result CCERR_VALID_SIGNATURE on signature success.
CCERR_INVALID_SIGNATURE on signature failure.
other on some other signature verification issue.
@discussion If the fault_canary_out argument is not NULL, the value `CCRSA_PSS_FAULT_CANARY` will be placed into fault_canary_out
if the salted input hash is equal to the decoded hash (which strongly implies the signature is valid). Callers can then securely compare this output buffer against CCRSA_PSS_FAULT_CANARY, using CC_FAULT_CANARY_EQUAL, as an additional check of signature validity: if the two canary values are equal, the signature is valid otherwise it is not. If the signature is valid and the canary values are NOT equal this may indicate a potentially injected computational fault.
*/
CC_NONNULL((1, 2, 3, 5, 7))
int ccrsa_verify_pss_digest(ccrsa_pub_ctx_t key,
const struct ccdigest_info* di,
const struct ccdigest_info* mgfdi,
size_t digest_nbytes, const uint8_t *cc_counted_by(digest_nbytes) digest,
size_t sig_nbytes, const uint8_t *cc_unsafe_indexable sig,
size_t salt_nbytes, cc_fault_canary_t fault_canary_out);
/*!
@function ccrsa_verify_pss_msg
@brief ccrsa_verify_pss_msg() verifies RSASSA-PSS signature in PKCS1-V2 format, given the message
@param key The RSA public key
@param di The hash algorithm used to generate the hash of the message.
@param mgfdi The hash algorithm for the mask generation function
@param msg_nbytes Length of message
@param msg The signed message
@param sig_nbytes The length of generated signature in bytes, which equals the size of the RSA modulus.
@param sig The signature to verify
@param salt_nbytes Length of the salt as used during signature generation.
@param fault_canary_out OPTIONAL cc_fault_canary_t (see discussion)
@result CCERR_VALID_SIGNATURE on signature success.
CCERR_INVALID_SIGNATURE on signature failure.
other on some other signature verification issue.
@discussion If the fault_canary_out argument is not NULL, the value `CCRSA_PSS_FAULT_CANARY` will be placed into fault_canary_out
if the salted input hash is equal to the decoded hash (which strongly implies the signature is valid). Callers can then securely compare this output buffer against CCRSA_PSS_FAULT_CANARY, using CC_FAULT_CANARY_EQUAL, as an additional check of signature validity: if the two canary values are equal, the signature is valid otherwise it is not. If the signature is valid and the canary values are NOT equal this may indicate a potentially injected computational fault.
*/
CC_NONNULL((1, 2, 3, 5, 7))
int ccrsa_verify_pss_msg(ccrsa_pub_ctx_t key,
const struct ccdigest_info* di,
const struct ccdigest_info* mgfdi,
size_t msg_nbytes, const uint8_t *cc_counted_by(msg_nbytes) msg,
size_t sig_nbytes, const uint8_t *cc_counted_by(sig_nbytes) sig,
size_t salt_nbytes, cc_fault_canary_t fault_canary_out);
/*!
@function ccrsa_sign_pkcs1v15
@abstract RSA signature with PKCS#1 v1.5 format per PKCS#1 v2.2
@param key Full key
@param oid OID describing the type of digest passed in
@param digest_len Byte length of the digest
@param digest Byte array of digest_len bytes containing the digest
@param sig_len Pointer to the number of bytes allocated for sig.
Output the exact size of the signature.
@param sig Pointer to the allocated buffer of size *sig_len
for the output signature
@result CCERR_OK iff successful.
@discussion Null OID is a special case, required to support RFC 4346 where the padding
is based on SHA1+MD5. In general it is not recommended to use a NULL OID,
except when strictly required for interoperability
*/
CC_NONNULL((1, 4, 5, 6))
int ccrsa_sign_pkcs1v15(ccrsa_full_ctx_t key, const uint8_t *oid,
size_t digest_len, const uint8_t *cc_counted_by(digest_len) digest,
size_t *sig_len, uint8_t *cc_unsafe_indexable sig);
/*!
@function ccrsa_sign_pkcs1v15_msg
@abstract RSA signature with PKCS#1 v1.5 format per PKCS#1 v2.2
@param key Full key
@param di Digest context
@param msg_len Byte length of the message to sign
@param msg Byte array of msg_len bytes containing the message. Will be hashed with di.
@param sig_len Pointer to the number of bytes allocated for sig.
Output the exact size of the signature.
@param sig Pointer to the allocated buffer of size *sig_len
for the output signature
@result CCERR_OK iff successful.
@discussion Null OID is not supported by this API.
*/
CC_NONNULL((1, 2, 4, 5, 6))
int ccrsa_sign_pkcs1v15_msg(ccrsa_full_ctx_t key, const struct ccdigest_info* di,
size_t msg_len, const uint8_t *cc_counted_by(msg_len) msg,
size_t *sig_len, uint8_t *cc_unsafe_indexable sig);
/*!
@function ccrsa_verify_pkcs1v15
@abstract RSA signature with PKCS#1 v1.5 format per PKCS#1 v2.2
@param key Public key
@param oid OID describing the type of digest passed in
@param digest_len Byte length of the digest
@param digest Byte array of digest_len bytes containing the digest
@param sig_len Number of bytes of the signature sig.
@param sig Pointer to the signature buffer of sig_len
@param valid Output boolean, true if the signature is valid.
@result A return value of 0 and valid = True indicates a valid signature.
A non-zero return value or valid = False indicates an invalid signature.
@discussion Null OID is a special case, required to support RFC 4346
where the padding is based on SHA1+MD5. In general it is not
recommended to use a NULL OID, except when strictly required for
interoperability.
*/
CC_NONNULL((1, 4, 6, 7))
int ccrsa_verify_pkcs1v15(ccrsa_pub_ctx_t key, const uint8_t *oid,
size_t digest_len, const uint8_t *cc_counted_by(digest_len) digest,
size_t sig_len, const uint8_t *cc_counted_by(sig_len) sig,
bool *valid);
/*!
@function ccrsa_verify_pkcs1v15_digest
@abstract RSA signature with PKCS#1 v1.5 format per PKCS#1 v2.2, given a digest
@param key Public key
@param oid OID describing the type of digest passed in
@param digest_len Byte length of the digest
@param digest Byte array of digest_len bytes containing the digest
@param sig_len Number of bytes of the signature sig.
@param sig Pointer to the signature buffer of sig_len
@param fault_canary_out OPTIONAL cc_fault_canary_t
@result CCERR_VALID_SIGNATURE if a valid signature.
CCERR_INVALID_SIGNATURE if an invalid signature.
Other if the verification procedure failed.
@discussion If the fault_canary_out argument is not NULL, the value `CCRSA_PKCS1_FAULT_CANARY` will be placed into fault_canary_out
if the input hash is equal to the decoded hash (which strongly implies the signature is valid). Callers can then securely compare this output buffer against CCRSA_PKCS1_FAULT_CANARY, using CC_FAULT_CANARY_EQUAL, as an additional check of signature validity: if the two canary values are equal, the signature is valid otherwise it is not. If the signature is valid and the canary values are NOT equal this may indicate a potentially injected computational fault.
*/
CC_NONNULL((1, 4, 6))
int ccrsa_verify_pkcs1v15_digest(ccrsa_pub_ctx_t key, const uint8_t *oid,
size_t digest_len, const uint8_t *cc_counted_by(digest_len) digest,
size_t sig_len, const uint8_t *cc_counted_by(sig_len) sig,
cc_fault_canary_t fault_canary_out);
/*!
@function ccrsa_verify_pkcs1v15_msg
@abstract RSA signature with PKCS#1 v1.5 format per PKCS#1 v2.2
@param key Public key
@param di Hash function
@param msg_len Byte length of the digest
@param msg Byte array of digest_len bytes containing the digest
@param sig_len Number of bytes of the signature sig.
@param sig Pointer to the signature buffer of sig_len
@param fault_canary_out OPTIONAL cc_fault_canary_t
@result CCERR_VALID_SIGNATURE if a valid signature.
CCERR_INVALID_SIGNATURE if an invalid signature.
Other if the verification procedure failed.
@discussion Null OID is not supported by this API.
If the fault_canary_out argument is not NULL, the value `CCRSA_PKCS1_FAULT_CANARY` will
be placed into fault_canary_out if the input hash is equal to the decoded hash (which strongly
implies the signature is valid). Callers can then securely compare this output buffer against CCRSA_PKCS1_FAULT_CANARY, using CC_FAULT_CANARY_EQUAL, as an additional check of signature validity: if the two canary values are equal, the signature is valid otherwise it is not. If the signature is valid and the canary values are NOT equal this may indicate a potentially injected computational fault.
*/
CC_NONNULL((1, 2, 4, 6))
int ccrsa_verify_pkcs1v15_msg(ccrsa_pub_ctx_t key, const struct ccdigest_info* di,
size_t msg_len, const uint8_t *cc_counted_by(msg_len) msg,
size_t sig_len, const uint8_t *cc_counted_by(sig_len) sig,
cc_fault_canary_t fault_canary_out);
/*!
@function ccder_encode_rsa_pub_size
@abstract Calculate size of public key export format data package.
@param key Public key
@result Returns size required for encoding.
*/
CC_NONNULL((1))
size_t ccder_encode_rsa_pub_size(const ccrsa_pub_ctx_t key);
/*!
@function ccrsa_export_priv_pkcs1
@abstract Export a public key.
@param key Public key
@param der Beginning of output DER buffer
@param der_end End of output DER buffer
*/
CC_NONNULL((1, 2, 3))
uint8_t *ccder_encode_rsa_pub(const ccrsa_pub_ctx_t key, uint8_t *cc_ended_by(der_end) der, uint8_t *der_end);
/*!
@function ccder_encode_rsa_priv_size
@abstract Calculate size of full key exported in PKCS#1 format.
@param key Full key
@result Returns size required for encoding.
*/
CC_NONNULL((1))
size_t ccder_encode_rsa_priv_size(const ccrsa_full_ctx_t key);
/*!
@function ccder_encode_rsa_priv
@abstract Export a full key in PKCS#1 format.
@param key Full key
@param der Beginning of output DER buffer
@param der_end End of output DER buffer
*/
CC_NONNULL((1, 2, 3))
uint8_t *ccder_encode_rsa_priv(const ccrsa_full_ctx_t key, const uint8_t *cc_ended_by(der_end) der, uint8_t *der_end);
/*!
@function ccder_decode_rsa_pub_n
@abstract Calculate "n" for a public key imported from a data package.
PKCS #1 format
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result the "n" of the RSA key that would result from the import. This can be used
to declare the key itself.
*/
CC_NONNULL((1, 2))
cc_size ccder_decode_rsa_pub_n(const uint8_t *cc_ended_by(der_end) der, const uint8_t *der_end);
/*!
@function ccder_decode_rsa_pub
@abstract Import a public RSA key from a package in public key format.
PKCS #1 format
@param key Public key (n must be set)
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result Key is initialized using the data in the public key message.
*/
CC_NONNULL((1, 2, 3))
const uint8_t *ccder_decode_rsa_pub(const ccrsa_pub_ctx_t key, const uint8_t *cc_ended_by(der_end) der, const uint8_t *der_end);
/*!
@function ccder_decode_rsa_pub_x509_n
@abstract Calculate "n" for a public key imported from a data package in x509 format
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result the "n" of the RSA key that would result from the import. This can be used
to declare the key itself.
*/
CC_NONNULL((1, 2))
cc_size ccder_decode_rsa_pub_x509_n(const uint8_t *cc_ended_by(der_end) der, const uint8_t *der_end);
/*!
@function ccder_decode_rsa_pub_x509
@abstract Import a public RSA key from a package in x509 format.
@param key Public key (n must be set)
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result Key is initialized using the data in the public key message.
*/
CC_NONNULL((1, 2, 3))
const uint8_t *ccder_decode_rsa_pub_x509(const ccrsa_pub_ctx_t key, const uint8_t *cc_ended_by(der_end) der, const uint8_t *der_end);
/*!
@function ccder_decode_rsa_priv_n
@abstract Calculate "n" for a private key imported from a data package.
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result the "n" of the RSA key that would result from the import. This can be used
to declare the key itself.
*/
CC_NONNULL((1, 2))
cc_size ccder_decode_rsa_priv_n(const uint8_t *cc_ended_by(der_end) der, const uint8_t *der_end);
/*!
@function ccder_decode_rsa_priv
@abstract Import a private RSA key from a package in PKCS#1 format.
@param key Full key (n must be set)
@param der Beginning of input DER buffer
@param der_end End of input DER buffer
@result Key is initialized using the data in the public key message.
*/
CC_NONNULL((1, 2, 3))
const uint8_t *ccder_decode_rsa_priv(const ccrsa_full_ctx_t key, const uint8_t *cc_ended_by(der_end) der, const uint8_t *der_end);
/*!
@function ccrsa_export_pub_size
@abstract Calculate size of public key exported data package.
@param key Public key
@result Returns size required for encoding.
*/
CC_NONNULL((1))
size_t ccrsa_export_pub_size(const ccrsa_pub_ctx_t key);
/*!
@function ccrsa_export_pub
@abstract Export a public key in public key format.
@param key Public key
@param out_len Allocated size
@param out Output buffer
*/
CC_NONNULL((1, 3))
int ccrsa_export_pub(const ccrsa_pub_ctx_t key, size_t out_len, uint8_t *cc_counted_by(out_len) out);
/*!
@function ccrsa_import_pub_n
@abstract Calculate "n" for a public key imported from a data package.
@param inlen Length of public key package data
@param der pointer to public key package data
@result the "n" of the RSA key that would result from the import. This can be used
to declare the key itself.
*/
CC_NONNULL((2))
cc_size ccrsa_import_pub_n(size_t inlen, const uint8_t *cc_sized_by(inlen) der);
/*!
@function ccrsa_import_pub
@abstract Import a public RSA key from a package in public key format.
@param key Public key (n must be set)
@param inlen Length of public key package data
@param der pointer to public key package data
@result Key is initialized using the data in the public key message.
*/
CC_NONNULL((1, 3))
int ccrsa_import_pub(ccrsa_pub_ctx_t key, size_t inlen, const uint8_t *cc_sized_by(inlen) der);
/*!
@function ccrsa_export_priv_size
@abstract Calculate size of full key exported in PKCS#1 format.
@param key Full key
@result Returns size required for encoding.
*/
CC_NONNULL((1))
size_t ccrsa_export_priv_size(const ccrsa_full_ctx_t key);
/*!
@function ccrsa_export_priv
@abstract Export a full key in PKCS#1 format.
@param key Full key
@param out_len Allocated size
@param out Output buffer
*/
CC_NONNULL((1, 3))
int ccrsa_export_priv(const ccrsa_full_ctx_t key, size_t out_len, uint8_t *cc_sized_by(out_len) out);
/*!
@function ccrsa_import_priv_n
@abstract Calculate size of full key exported in PKCS#1 format.
@param inlen Length of PKCS#1 package data
@param der pointer to PKCS#1 package data
@result the "n" of the RSA key that would result from the import. This can be used
to declare the key itself.
*/
CC_NONNULL((2))
cc_size ccrsa_import_priv_n(size_t inlen, const uint8_t *cc_sized_by(inlen) der);
/*!
@function ccrsa_import_priv
@abstract Import a full RSA key from a package in PKCS#1 format.
@param key Full key (n must be set)
@param inlen Length of PKCS#1 package data
@param der pointer to PKCS#1 package data
@result Key is initialized using the data in the PKCS#1 message.
*/
CC_NONNULL_ALL
int ccrsa_import_priv(ccrsa_full_ctx_t key, size_t inlen, const uint8_t *cc_sized_by(inlen) der);
/*!
@function ccrsa_get_pubkey_components
@abstract Copy each component of the public key to the given buffers
@param pubkey Public key
@param modulus Buffer to the output buffer for the modulus
@param modulusLength Pointer to the byte size allocated for the modulus, updated with actual output size
@param exponent Buffer to the output buffer for the exponent
@param exponentLength Pointer to the byte size allocated for the exponent, updated with actual output size
@return 0 is success, not 0 in case of error
@discussion if either allocated buffer length is insufficient, the function returns an error
*/
CC_NONNULL((1, 2))
int ccrsa_get_pubkey_components(const ccrsa_pub_ctx_t pubkey, uint8_t *cc_unsafe_indexable modulus, size_t *modulusLength, uint8_t *cc_unsafe_indexable exponent, size_t *exponentLength);
/*!
@function ccrsa_get_fullkey_components
@abstract Copy each component of the public key to the given buffers
@param key Full key
@param modulus Output buffer for the modulus
@param modulusLength Pointer to the byte size allocated for the modulus, updated with actual output size
@param d Output buffer for the private exponent d.
@param dLength Pointer to the byte size allocated for the private exponent d, updated with actual output size
@param p Output buffer for the first prime factor of the modulus
@param pLength Pointer to the byte size allocated for the prime factor, updated with actual output size
@param q Output buffer for the second prime factor of the modulus
@param qLength Pointer to the byte size allocated for the prime factor, updated with actual output size
@return 0 is success, not 0 in case of error
@discussion if either allocated buffer length is insufficient, the function returns an error
*/
CC_NONNULL((1, 2))
int ccrsa_get_fullkey_components(const ccrsa_full_ctx_t key, uint8_t *cc_unsafe_indexable modulus, size_t *modulusLength,
uint8_t *cc_unsafe_indexable d, size_t *dLength,
uint8_t *cc_unsafe_indexable p, size_t *pLength,
uint8_t *cc_unsafe_indexable q, size_t *qLength);
/*!
@function ccrsa_dump_public_key
@abstract Print a rsa public key in the console (printf)
@param key Public key
*/
void ccrsa_dump_public_key(ccrsa_pub_ctx_t key);
/*!
@function ccrsa_dump_full_key
@abstract Print a rsa private key in the console (printf)
@param key Public key
*/
void ccrsa_dump_full_key(ccrsa_full_ctx_t key);
#endif /* _CORECRYPTO_CCRSA_H_ */

View file

@ -0,0 +1,40 @@
/* Copyright (c) (2010,2011,2012,2014,2015,2016,2017,2018,2019) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCSHA1_H_
#define _CORECRYPTO_CCSHA1_H_
#include <corecrypto/ccdigest.h>
#include <corecrypto/cc_config.h>
#define CCSHA1_BLOCK_SIZE 64
#define CCSHA1_OUTPUT_SIZE 20
#define CCSHA1_STATE_SIZE 20
/* sha1 selector */
const struct ccdigest_info *ccsha1_di(void);
/* Implementations */
extern const struct ccdigest_info ccsha1_ltc_di;
extern const struct ccdigest_info ccsha1_eay_di;
#if CCSHA1_VNG_INTEL
extern const struct ccdigest_info ccsha1_vng_intel_SupplementalSSE3_di;
#endif
#if CCSHA1_VNG_ARM
extern const struct ccdigest_info ccsha1_vng_arm_di;
#endif
#define ccoid_sha1 ((unsigned char *)"\x06\x05\x2b\x0e\x03\x02\x1a")
#define ccoid_sha1_len 7
#endif /* _CORECRYPTO_CCSHA1_H_ */

View file

@ -0,0 +1,83 @@
/* Copyright (c) (2010-2012,2014-2019,2021,2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCSHA2_H_
#define _CORECRYPTO_CCSHA2_H_
#include <corecrypto/ccdigest.h>
CC_PTRCHECK_CAPABLE_HEADER()
/* sha2 selectors */
const struct ccdigest_info *ccsha224_di(void);
const struct ccdigest_info *ccsha256_di(void);
const struct ccdigest_info *ccsha384_di(void);
const struct ccdigest_info *ccsha512_di(void);
const struct ccdigest_info *ccsha512_256_di(void); // SHA512/256 (cf FIPS 180-4 https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf)
#define ccoid_sha224 ((unsigned char *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x04")
#define ccoid_sha224_len 11
#define ccoid_sha256 ((unsigned char *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x01")
#define ccoid_sha256_len 11
#define ccoid_sha384 ((unsigned char *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x02")
#define ccoid_sha384_len 11
#define ccoid_sha512 ((unsigned char *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x03")
#define ccoid_sha512_len 11
#define ccoid_sha512_256 ((unsigned char *)"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x02\x06")
#define ccoid_sha512_256_len 11
/* SHA256 */
#define CCSHA256_BLOCK_SIZE 64
#define CCSHA256_OUTPUT_SIZE 32
#define CCSHA256_STATE_SIZE 32
extern const struct ccdigest_info ccsha256_ltc_di;
#if CCSHA2_VNG_INTEL
extern const struct ccdigest_info ccsha224_vng_intel_SupplementalSSE3_di;
extern const struct ccdigest_info ccsha256_vng_intel_SupplementalSSE3_di;
#endif
#if CCSHA2_VNG_ARM
extern const struct ccdigest_info ccsha224_vng_arm_di;
extern const struct ccdigest_info ccsha256_vng_arm_di;
#if defined(__arm64__)
extern const struct ccdigest_info ccsha256_vng_arm64neon_di;
#endif
extern const struct ccdigest_info ccsha384_vng_arm_di;
extern const struct ccdigest_info ccsha512_vng_arm_di;
extern const struct ccdigest_info ccsha512_256_vng_arm_di;
#endif
/* SHA224 */
#define CCSHA224_OUTPUT_SIZE 28
extern const struct ccdigest_info ccsha224_ltc_di;
/* SHA512 */
#define CCSHA512_BLOCK_SIZE 128
#define CCSHA512_OUTPUT_SIZE 64
#define CCSHA512_STATE_SIZE 64
extern const struct ccdigest_info ccsha512_ltc_di;
/* SHA512/256 */
// FIPS 180-4
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
#define CCSHA512_256_BLOCK_SIZE 128
#define CCSHA512_256_OUTPUT_SIZE 32
#define CCSHA512_256_STATE_SIZE 64
extern const struct ccdigest_info ccsha512_256_ltc_di;
/* SHA384 */
#define CCSHA384_OUTPUT_SIZE 48
extern const struct ccdigest_info ccsha384_ltc_di;
#endif /* _CORECRYPTO_CCSHA2_H_ */

View file

@ -0,0 +1,56 @@
/* Copyright (c) (2010-2022) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_CCZP_H_
#define _CORECRYPTO_CCZP_H_
#include <corecrypto/ccn.h>
CC_PTRCHECK_CAPABLE_HEADER()
struct cczp;
typedef struct cczp *cczp_t;
typedef const struct cczp *cczp_const_t;
struct cczp_funcs;
typedef const struct cczp_funcs *cczp_funcs_t;
// keep cczp_hd and cczp structures consistent
// cczp_hd is typecasted to cczp to read EC curve params
// make sure n is the first element see ccrsa_ctx_n macro
#define __CCZP_HEADER_ELEMENTS_DEFINITIONS(pre) \
cc_size pre##n; \
cc_unit pre##bitlen; \
cczp_funcs_t pre##funcs;
#define __CCZP_ELEMENTS_DEFINITIONS(pre) \
__CCZP_HEADER_ELEMENTS_DEFINITIONS(pre) \
cc_unit pre##ccn[];
struct cczp {
__CCZP_ELEMENTS_DEFINITIONS()
} CC_ALIGNED(CCN_UNIT_SIZE);
#define CCZP_N(ZP) ((ZP)->n)
#define CCZP_PRIME(ZP) ((ZP)->ccn)
#define CCZP_BITLEN(ZP) ((ZP)->bitlen)
CC_NONNULL((1))
cc_size cczp_n(cczp_const_t zp);
CC_NONNULL((1))
const cc_unit * cc_indexable cczp_prime(cczp_const_t zp);
CC_NONNULL((1))
size_t cczp_bitlen(cczp_const_t zp);
#endif /* _CORECRYPTO_CCZP_H_ */

View file

@ -0,0 +1,46 @@
/* Copyright (c) (2017,2019) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#ifndef _CORECRYPTO_FIPSPOST_TRACE_H_
#define _CORECRYPTO_FIPSPOST_TRACE_H_
#if CC_FIPSPOST_TRACE
/*
* Use this string to separate out tests.
*/
#define FIPSPOST_TRACE_TEST_STR "?"
int fipspost_trace_is_active(void);
void fipspost_trace_call(const char *fname);
/* Only trace when VERBOSE is set to avoid impacting normal boots. */
#define FIPSPOST_TRACE_EVENT do { \
if (fipspost_trace_is_active()) { \
fipspost_trace_call(__FUNCTION__); \
} \
} while (0);
#define FIPSPOST_TRACE_MESSAGE(MSG) do { \
if (fipspost_trace_is_active()) { \
fipspost_trace_call(MSG); \
} \
} while (0);
#else
/* Not building a CC_FIPSPOST_TRACE-enabled, no TRACE operations. */
#define FIPSPOST_TRACE_EVENT
#define FIPSPOST_TRACE_MESSAGE(X)
#endif
#endif

View file

@ -0,0 +1,210 @@
/*!
* @header
* Supported coprocessors.
*/
#ifndef __IMAGE4_API_COPROCESSOR_H
#define __IMAGE4_API_COPROCESSOR_H
#include <image4/image4.h>
#include <image4/types.h>
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @const IMAGE4_COPROCESSOR_HOST
* The host execution environment. This environment does not support handles.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT
const image4_coprocessor_t _image4_coprocessor_host;
#define IMAGE4_COPROCESSOR_HOST (&_image4_coprocessor_host)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_coprocessor_host);
/*!
* @const IMAGE4_COPROCESSOR_AP
* The Application Processor executing payloads signed by the Secure Boot CA.
*
* Handles for this environment are enumerated in the
* {@link image4_coprocessor_ap_handle_t} type.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT
const image4_coprocessor_t _image4_coprocessor_ap;
#define IMAGE4_COPROCESSOR_AP (&_image4_coprocessor_ap)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_coprocessor_ap);
/*!
* @typedef image4_coprocessor_handle_ap_t
* Handles describing supported AP execution environments.
*
* @const IMAGE4_COPROCESSOR_HANDLE_AP
* The host's Application Processor environment.
*
* @const IMAGE4_COPROCESSOR_HANDLE_AP_FF00
* The software AP environment used for loading globally-signed OTA update brain
* trust caches.
*
* @const IMAGE4_COPROCESSOR_HANDLE_AP_FF01
* The software AP environment used for loading globally-signed Install
* Assistant brain trust caches.
*
* @const IMAGE4_COPROCESSOR_HANDLE_AP_FF06
* The software AP environment used for loading globally-signed Bootability
* brain trust caches.
*
* @const IMAGE4_COPROCESSOR_HANDLE_AP_PDI
* The sideloading AP environment used to load a personalized disk image.
*
* @const IMAGE4_COPROCESSOR_HANDLE_AP_SRDP
* The sideloading AP environment used to load firmware which has been
* authorized as part of the Security Research Device Program.
*
* @const IMAGE4_COPROCESSOR_HANDLE_AP_DDI
* The sideloading AP environment used to load a personalized disk image which
* is automatically mounted at boot.
*
* This handle is available starting in API version 20231027.
*/
OS_CLOSED_ENUM(image4_coprocessor_handle_ap, image4_coprocessor_handle_t,
IMAGE4_COPROCESSOR_HANDLE_AP = 0,
IMAGE4_COPROCESSOR_HANDLE_AP_FF00,
IMAGE4_COPROCESSOR_HANDLE_AP_FF01,
IMAGE4_COPROCESSOR_HANDLE_AP_FF06,
IMAGE4_COPROCESSOR_HANDLE_AP_PDI,
IMAGE4_COPROCESSOR_HANDLE_AP_SRDP,
IMAGE4_COPROCESSOR_HANDLE_AP_RESERVED_0,
IMAGE4_COPROCESSOR_HANDLE_AP_RESERVED_1,
IMAGE4_COPROCESSOR_HANDLE_AP_RESERVED_2,
IMAGE4_COPROCESSOR_HANDLE_AP_DDI,
_IMAGE4_COPROCESSOR_HANDLE_AP_CNT,
);
/*!
* @const IMAGE4_COPROCESSOR_AP_LOCAL
* The Application Processor executing payloads signed by the Basic Attestation
* Authority.
*
* Handles for this environment are enumerated in the
* {@link image4_coprocessor_handle_ap_local_t} type.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT
const image4_coprocessor_t _image4_coprocessor_ap_local;
#define IMAGE4_COPROCESSOR_AP_LOCAL (&_image4_coprocessor_ap_local)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_coprocessor_ap_local);
/*!
* @typedef image4_coprocessor_handle_ap_local_t
* Handles describing supported local policy execution environments.
*
* @const IMAGE4_COPROCESSOR_HANDLE_AP_LOCAL
* The host's local policy environment.
*/
OS_CLOSED_ENUM(image4_coprocessor_handle_ap_local, image4_coprocessor_handle_t,
IMAGE4_COPROCESSOR_HANDLE_AP_LOCAL = 0,
IMAGE4_COPROCESSOR_HANDLE_AP_LOCAL_RESERVED_0,
IMAGE4_COPROCESSOR_HANDLE_AP_LOCAL_RESERVED_1,
IMAGE4_COPROCESSOR_HANDLE_AP_LOCAL_RESERVED_2,
_IMAGE4_COPROCESSOR_HANDLE_AP_LOCAL_CNT,
);
/*!
* @const IMAGE4_COPROCESSOR_CRYPTEX1
* The Cryptex1 coprocessor executing payloads signed by the Secure Boot CA.
*
* Handles for this environment are enumerated in the
* {@link image4_coprocessor_handle_cryptex1_t} type.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT
const image4_coprocessor_t _image4_coprocessor_cryptex1;
#define IMAGE4_COPROCESSOR_CRYPTEX1 (&_image4_coprocessor_cryptex1)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_coprocessor_cryptex1);
/*!
* @typedef image4_coprocessor_handle_cryptex1_t
* Handles describing supported Cryptex1 execution environments.
*
* @const IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_BOOT
* The host's Cryptex1 boot coprocessor.
*
* @const IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_BOOT_LIVE
* The host's Cryptex1 boot coprocessor used for executing newly-authorized
* firmware prior to that firmware being evaluated by Secure Boot.
*
* @const IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_ASSET_BRAIN
* The host's Cryptex1 coprocessor used for loading MobileAsset brain firmware.
*
* @const IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_GENERIC
* The host's Cryptex1 coprocessor used for loading generic supplemental
* content.
*/
OS_CLOSED_ENUM(image4_coprocessor_handle_cryptex1, image4_coprocessor_handle_t,
IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_BOOT = 0,
IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_BOOT_LIVE,
IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_ASSET_BRAIN,
IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_GENERIC,
IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_RESERVED_0,
IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_RESERVED_1,
IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_RESERVED_2,
_IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_CNT,
);
/*!
* @const IMAGE4_COPROCESSOR_SEP
* The Secure Enclave Processor executing payloads signed by the Secure Boot CA.
*
* Handles for this environment are enumerated in the
* {@link image4_coprocessor_handle_sep_t} type.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT
const image4_coprocessor_t _image4_coprocessor_sep;
#define IMAGE4_COPROCESSOR_SEP (&_image4_coprocessor_sep)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_coprocessor_sep);
/*!
* @typedef image4_coprocessor_handle_sep_t
* Handles describing supported SEP execution environments.
*
* @const IMAGE4_COPROCESSOR_HANDLE_SEP
* The host's SEP environment.
*/
OS_CLOSED_ENUM(image4_coprocessor_handle_sep, image4_coprocessor_handle_t,
IMAGE4_COPROCESSOR_HANDLE_SEP = 0,
_IMAGE4_COPROCESSOR_HANDLE_SEP_CNT,
);
/*!
* @const IMAGE4_COPROCESSOR_X86
* An x86 processor executing payloads signed by the x86 Secure Boot CA.
*
* Handles for this environment are enumerated in the
* {@link image4_coprocessor_handle_x86_t} type.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT
const image4_coprocessor_t _image4_coprocessor_x86;
#define IMAGE4_COPROCESSOR_X86 (&_image4_coprocessor_x86)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_coprocessor_x86);
/*!
* @typedef image4_coprocessor_handle_x86_t
* Handles describing supported x86 execution environments.
*
* @const IMAGE4_COPROCESSOR_HANDLE_X86
* The host's x86 environment.
*/
OS_CLOSED_ENUM(image4_coprocessor_handle_x86, image4_coprocessor_handle_t,
IMAGE4_COPROCESSOR_HANDLE_X86 = 0,
_IMAGE4_COPROCESSOR_HANDLE_X86_CNT,
);
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMAGE4_API_COPROCESSOR_H

View file

@ -0,0 +1,73 @@
/*
* Copyright © 2017-2024 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*!
* @header
* Definitions and interfaces for handling Cryptex1 nonces on Darwin platforms.
*/
#ifndef __IMAGE4_DARWIN_CRYPTEX1_NONCE_H
#define __IMAGE4_DARWIN_CRYPTEX1_NONCE_H
#include <os/base.h>
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
/*!
* @typedef darwin_cryptex1_nonce_t
* A type describing nonce handle values for Cryptex1 nonce domains hosted on
* Darwin.
*
* @const DARWIN_CRYPTEX1_NONCE_BOOT
* The Cryptex1 boot nonce.
*
* @const DARWIN_CRYPTEX1_NONCE_ASSET_BRAIN
* The Cryptex1 MobileAsset brain nonce.
*
* @const DARWIN_CRYPTEX1_NONCE_GENERIC
* The Cryptex1 generic nonce.
*
* @const DARWIN_CRYPTEX1_NONCE_SIMULATOR_RUNTIME
* The Cryptex1 simulator runtime nonce.
*
* @const DARWIN_CRYPTEX1_NONCE_EPHEMERAL
* The Cryptex1 ephemeral nonce. This nonce is suitable for any ephemeral
* personalization.
*/
OS_CLOSED_ENUM(darwin_cryptex1_nonce, uint32_t,
DARWIN_CRYPTEX1_NONCE_BOOT = 1,
DARWIN_CRYPTEX1_NONCE_ASSET_BRAIN = 2,
DARWIN_CRYPTEX1_NONCE_GENERIC = 3,
DARWIN_CRYPTEX1_NONCE_SIMULATOR_RUNTIME = 4,
DARWIN_CRYPTEX1_NONCE_EPHEMERAL = 5,
_DARWIN_CRYPTEX1_NONCE_CNT,
);
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMAGE4_DARWIN_CRYPTEX1_NONCE_H

View file

@ -0,0 +1,56 @@
/*
* Copyright © 2017-2024 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*!
* @header
* Structures and definitions which are specific to the PPL incarnation of the
* kernel's code signing monitor.
*/
#ifndef __IMAGE4_CS_PMAP_H
#define __IMAGE4_CS_PMAP_H
#include <os/base.h>
#include <stdint.h>
#include <sys/types.h>
#include <image4/image4.h>
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @const IMAGE4_CS_PMAP_DATA_SIZE
* The size of the memory region which the PPL should reserve on behalf of the
* GL2 expert.
*/
#define IMAGE4_CS_PMAP_DATA_SIZE (5120u)
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMAGE4_CS_PMAP_H

View file

@ -0,0 +1,269 @@
/*
* Copyright © 2017-2024 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*!
* @header
* Structures and trap handler declarations for use in the kernel's code signing
* monitor. On targets which have a PPL, these mediate traps between the EL2 and
* GL2 experts. On targets which have a TXM, these mediate traps from EL2 to
* GL0, which uses libimage4_TXM and not the kernel implementation.
*/
#ifndef __IMAGE4_CS_TRAPS_H
#define __IMAGE4_CS_TRAPS_H
#include <os/base.h>
#include <stdint.h>
#include <sys/types.h>
#include <image4/image4.h>
#if XNU_KERNEL_PRIVATE
#include <sys/_types/_ssize_t.h>
#if !defined(IMAGE4_DIAGNOSTIC_TRAP_LEVEL)
#if DEBUG || KASAN
#define IMAGE4_DIAGNOSTIC_TRAP_LEVEL 2
#elif DEVELOPMENT
#define IMAGE4_DIAGNOSTIC_TRAP_LEVEL 1
#elif RELEASE
#define IMAGE4_DIAGNOSTIC_TRAP_LEVEL 0
#else
#define IMAGE4_DIAGNOSTIC_TRAP_LEVEL 0
#endif
#endif // !defined(IMAGE4_DIAGNOSTIC_TRAP_LEVEL)
#endif // XNU_KERNEL_PRIVATE
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @const IMAGE4_CS_API_VERSION
* The version of the trap API which is supported by the current implementation.
* Successive versions will only introduce new traps. If a trap's ABI has to
* change, a new trap will be introduced, and the old one retired.
*/
#define IMAGE4_CS_API_VERSION (0u)
#pragma mark Parameter Attributes
/*!
* @const __cs_copy
* The trap vector parameter is fixed-size and should be copied into the
* supervisor's address space.
*/
#define __cs_copy
/*!
* @const __cs_xfer
* The trap vector parameter is a pointer with an associated length, and control
* of the subject memory should be transferred to the supervisor permanently.
*/
#define __cs_xfer
/*!
* @const __cs_borrow
* The trap vector parameter is a pointer with an associated length, and control
* of the subject memory should be temporarily transferred to the supervisor,
* being returned at the conclusion of the trap.
*/
#define __cs_borrow
/*!
* @const __cs_nullable
* The trap vector parameter is a pointer which may be NULL.
*/
#define __cs_nullable
/*!
* @const __cs_diagnostic
* Indicates that the trap vector is for a trap which is only implemented in
* DEBUG build variants.
*/
#define __cs_diagnostic
#pragma mark Types
/*!
* @typedef image4_cs_addr_t
* A type representing an address used in a trap argument vector.
*/
typedef uintptr_t image4_cs_addr_t;
/*!
* @enum image4_cs_trap_t
* An enumeration describing all supported traps from the EL2 expert to its
* code signing supervisor.
*
* @const IMAGE4_CS_TRAP_KMOD_SET_RELEASE_TYPE
* Set the OS release type to inform the availability of the research cryptex
* nonce. Can only be called once.
*
* @const IMAGE4_CS_TRAP_NONCE_SET
* Sets the active nonce for a nonce domain. Both the cleartext nonce and its
* encrypted form are set.
*
* @const IMAGE4_CS_TRAP_NONCE_ROLL
* Marks a nonce as rolled such that it new trust evaluations using the nonce
* will fail. The nonce will be re-generated at the next boot.
*
* @const IMAGE4_CS_TRAP_IMAGE_ACTIVATE
* Activates an image in the GL2 context.
*
* @const IMAGE4_CS_TRAP_SET_BOOT_UUID
* Set the boot session UUID to inform nonce choices for MobileAsset.
*/
OS_CLOSED_ENUM(image4_cs_trap, uint64_t,
IMAGE4_CS_TRAP_KMOD_SET_RELEASE_TYPE,
IMAGE4_CS_TRAP_NONCE_SET,
IMAGE4_CS_TRAP_NONCE_ROLL,
IMAGE4_CS_TRAP_IMAGE_ACTIVATE,
IMAGE4_CS_TRAP_KMOD_SET_BOOT_UUID,
_IMAGE4_CS_TRAP_CNT,
);
/*!
* @typedef image4_cs_trap_handler_t
* A handler for a GL2 or GL0 trap.
*
* @param csmx
* The trap code.
*
* @param argv
* The input argument structure.
*
* @param argv_len
* The length of {@link argv}.
*
* @param argv_out
* The output argument structure. Upon successful return, this structure will be
* populated. Otherwise, the implementation will not modify this memory.
*
* @param argv_out_len
* The length of {@link argv_out}.
*
* @result
* Upon success, zero is returned. Upon failure, a POSIX error code describing
* the failure condition.
*/
typedef errno_t (*image4_cs_trap_handler_t)(
image4_cs_trap_t csmx,
const void *argv,
size_t argv_len,
void *_Nullable argv_out,
size_t *_Nullable argv_out_len
);
/*!
* @function image4_cs_trap_handler
* Macro which expands to a function name suitable for a trap handler.
*
* @param _el
* The execution level in which the trap resides.
*
* @param _where
* The subsystem of the trap.
*
* @param _which
* The name of the trap.
*/
#define image4_cs_trap_handler(_el, _where, _which) \
_image4_ ## _el ## _cs_trap_ ## _where ## _ ## _which
#pragma mark Trap Arguments
#define image4_cs_trap_argv(_which) \
image4_cs_trap_argv_ ## _which ## _t
#define image4_cs_trap_argv_decl(_which) \
typedef struct _image4_cs_trap_argv_ ## _which \
image4_cs_trap_argv(_which); \
struct __attribute__((packed)) _image4_cs_trap_argv_ ## _which
image4_cs_trap_argv_decl(kmod_set_release_type) {
char __cs_copy csmx_release_type[64];
};
image4_cs_trap_argv_decl(kmod_set_boot_uuid) {
uint8_t __cs_copy csmx_uuid[16];
};
image4_cs_trap_argv_decl(nonce_set) {
uint64_t csmx_handle;
uint32_t csmx_flags;
uint8_t __cs_copy csmx_clear[16];
uint8_t __cs_copy csmx_cipher[16];
};
image4_cs_trap_argv_decl(nonce_roll) {
uint64_t csmx_handle;
};
image4_cs_trap_argv_decl(image_activate) {
uint64_t csmx_handle;
image4_cs_addr_t __cs_xfer csmx_payload;
uint32_t csmx_payload_len;
image4_cs_addr_t __cs_xfer csmx_manifest;
uint32_t csmx_manifest_len;
};
#pragma mark API
/*!
* @function image4_cs_trap_resolve_handler
* Resolves a trap code to a handler function.
*
* @param trap
* The trap code to resolve.
*
* @result
* A function pointer corresponding to the entry point for the given trap code.
* If the given trap is not implemented, NULL is returned.
*/
OS_EXPORT OS_WARN_RESULT
image4_cs_trap_handler_t _Nullable
image4_cs_trap_resolve_handler(image4_cs_trap_t trap);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_cs_trap_resolve_handler);
/*!
* @function image4_cs_trap_vector_size
* Returns the expected size of the argument vector for the provided trap.
*
* @param trap
* The trap code for which to obtain the size.
*
* @result
* The size of the argument vector in bytes of the provided trap. If the trap
* number is invalid or not supported by the implementation, -1 is returned.
*/
OS_EXPORT OS_WARN_RESULT
ssize_t
image4_cs_trap_vector_size(image4_cs_trap_t trap);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_cs_trap_vector_size);
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMAGE4_CS_TRAPS_H

View file

@ -0,0 +1,591 @@
/*!
* @header
* Encapsulation which describes an Image4 environment. The environment
* encompasses chip properties and trust evaluation policies, including digest
* algorithm selection and secure boot level enforcement.
*/
#ifndef __IMAGE4_API_ENVIRONMENT_H
#define __IMAGE4_API_ENVIRONMENT_H
#include <image4/image4.h>
#include <image4/types.h>
#include <image4/coprocessor.h>
#include <stdbool.h>
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
#pragma mark Forward Types
/*!
* @typedef image4_environment_storage_t
* The canonical type for environment storage.
*/
typedef struct _image4_environment_storage image4_environment_storage_t;
/*!
* @typedef image4_environment_query_boot_nonce_t
* A callback to provide the boot nonce for the environment.
*
* @param env
* The environment for which to retrieve the boot nonce.
*
* @param n
* Storage in which the callee should write the nonce upon successful return.
*
* @param n_len
* Storage in which the callee should write the nonce length upon successful
* return.
*
* On function entry, the content of this parameter is undefined.
*
* @param _ctx
* The context pointer which was provided during the environment's construction.
*
* @result
* The callee is expected to return zero on success. Otherwise, the callee may
* return one of the following POSIX error codes:
*
* [ENOTSUP] Obtaining the boot nonce is not supported; this will cause the
* implementation to act as if no callback was specified
* [ENOENT] The boot nonce does not exist
* [ENXIO] The boot nonce is not yet available for the environment, and
* the environment's bootstrap nonce (if any) should be used for
* anti-replay instead
*
* @discussion
* This callback is utilized by exec, sign, and boot trust evaluations.
*/
typedef errno_t (*image4_environment_query_boot_nonce_t)(
const image4_environment_t *env,
uint8_t n[__static_size _Nonnull IMAGE4_NONCE_MAX_LEN],
size_t *n_len,
void *_ctx
);
/*!
* @typedef image4_environment_query_nonce_digest_t
* A callback to provide a nonce digest for use during preflight trust
* evaluations.
*
* @param env
* The environment for which to retrieve the boot nonce.
*
* @param nd
* Storage in which the callee should write the nonce digest upon successful
* return.
*
* @param nd_len
* Storage in which the callee should write the nonce digest length upon
* successful return.
*
* On function entry, the content of this parameter is undefined.
*
* @param _ctx
* The context pointer which was provided during the environment's construction.
*
* @result
* The callee is expected to return zero on success. Otherwise, the callee may
* return one of the following POSIX error codes:
*
* [ENOTSUP] Obtaining the nonce digest is not supported; this will cause
* the implementation to act as if no callback was specified
* [ENOENT] The nonce digest does not exist
*
* @discussion
* This callback is utilized by preflight, sign, and boot trust evaluations. In
* sign and trust trust evaluations, it is only called if the nonce itself
* cannot be obtained from either the environment internally or the boot nonce
* callback.
*/
typedef errno_t (*image4_environment_query_nonce_digest_t)(
const image4_environment_t *env,
uint8_t nd[__static_size _Nonnull IMAGE4_NONCE_DIGEST_MAX_LEN],
size_t *nd_len,
void *_ctx
);
/*!
* @typedef image4_environment_identifier_bool_t
* A callback which conveys the value of a Boolean identifier associated with
* the environment during an identification.
*
* @param nv
* The environment which is being identified.
*
* @param id4
* The Boolean identifier.
*
* @param val
* The value of the identifier.
*
* @param _ctx
* The context pointer which was provided during the environment's construction.
*/
typedef void (*image4_environment_identifier_bool_t)(
const image4_environment_t *nv,
const image4_identifier_t *id4,
bool val,
void *_ctx
);
/*!
* @typedef image4_environment_identifier_integer_t
* A callback which conveys the value of an unsigned 64-bit integer identifier
* associated with the environment during an identification.
*
* @param nv
* The environment which is being identified.
*
* @param id4
* The integer identifier.
*
* @param val
* The value of the identifier.
*
* @param _ctx
* The context pointer which was provided during the environment's construction.
*/
typedef void (*image4_environment_identifier_integer_t)(
const image4_environment_t *nv,
const image4_identifier_t *id4,
uint64_t val,
void *_ctx
);
/*!
* @typedef image4_environment_identifier_data_t
* A callback which conveys the value of an octet string identifier associated
* with the environment during an identification.
*
* @param nv
* The environment which is being identified.
*
* @param id4
* The octet string identifier.
*
* @param vp
* A pointer to the octet string bytes.
*
* @param vp_len
* The length of the octet string indicated by {@link vp}.
*
* @param _ctx
* The context pointer which was provided during the environment's construction.
*/
typedef void (*image4_environment_identifier_data_t)(
const image4_environment_t *nv,
const image4_identifier_t *id4,
const void *vp,
size_t vp_len,
void *_ctx
);
/*!
* @const IMAGE4_ENVIRONMENT_CALLBACKS_STRUCT_VERSION
* The version of the {@link image4_environment_callbacks_t} structure supported
* by the implementation.
*/
#define IMAGE4_ENVIRONMENT_CALLBACKS_STRUCT_VERSION (0u)
/*!
* @struct image4_environment_callbacks_t
* A callback structure which may be given to influence the behavior of an
* {@link image4_environment_t}.
*
* @field nvcb_version
* The version of the structure. Initialize to
* {@link IMAGE4_ENVIRONMENT_CALLBACKS_STRUCT_VERSION}.
*
* @field nvcb_query_boot_nonce
* The callback to query the boot nonce.
*
* @field nvcb_query_nonce_digest
* The callback to query a nonce digest.
*
* @field nvcb_construct_boot
* The callback to construct the boot sequence for the environment.
*
* @field nvcb_identifier_bool
* The callback to convey a Boolean identifier in the environment.
*
* @field nvcb_identifier_integer
* The callback to convey an integer identifier in the environment.
*
* @field nvcb_identifier_data
* The callback to convey an octet string identifier in the environment.
*/
typedef struct _image4_environment_callbacks {
image4_struct_version_t nvcb_version;
image4_environment_query_boot_nonce_t _Nullable nvcb_query_boot_nonce;
image4_environment_query_nonce_digest_t _Nullable nvcb_query_nonce_digest;
image4_environment_identifier_bool_t _Nullable nvcb_identifier_bool;
image4_environment_identifier_integer_t _Nullable nvcb_identifier_integer;
image4_environment_identifier_data_t _Nullable nvcb_identifier_data;
} image4_environment_callbacks_t;
/*!
* @const IMAGE4_ENVIRONMENT_STRUCT_VERSION
* The version of the {@link image4_environment_t} structure supported by the
* implementation.
*/
#define IMAGE4_ENVIRONMENT_STRUCT_VERSION (0u)
/*!
* @struct image4_environment_storage_t
* An opaque structure which is guaranteed to be large enough to accommodate an
* {@link image4_environment_t}.
*
* @field __opaque
* The opaque storage.
*/
struct _image4_environment_storage {
uint8_t __opaque[256];
};
/*!
* @const IMAGE4_TRUST_STORAGE_INIT
* Initializer for a {@link image4_environment_storage_t} object.
*/
#define IMAGE4_ENVIRONMENT_STORAGE_INIT (image4_environment_storage_t){ \
.__opaque = { 0x00 }, \
}
#pragma mark API
/*!
* @function image4_environment_init
* Initializes an environment in which to perform a trust evaluation.
*
* @param storage
* The storage structure.
*
* @param coproc
* The coprocessor which will perform the evaluation. If NULL,
* {@link IMAGE4_COPROCESSOR_HOST} will be assumed.
*
* @param handle
* The specific environment and policy within the coprocessor to use for
* performing the evaluation. If {@link IMAGE4_COPROCESSOR_HOST} is used, this
* parameter is ignored.
*
* @result
* An initialized {@link image4_environment_t} object.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
image4_environment_t *
_image4_environment_init(
image4_environment_storage_t *storage,
const image4_coprocessor_t *_Nullable coproc,
image4_coprocessor_handle_t handle,
image4_struct_version_t v);
#define image4_environment_init(_storage, _coproc, _handle) \
_image4_environment_init( \
(_storage), \
(_coproc), \
(_handle), \
IMAGE4_ENVIRONMENT_STRUCT_VERSION)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_environment_init);
/*!
* @function image4_environment_new
* Allocates an environment in which to perform a trust evaluation.
*
* @param coproc
* The coprocessor which will perform the evaluation. If NULL,
* {@link IMAGE4_COPROCESSOR_HOST} will be assumed.
*
* @param handle
* The specific environment and policy within the coprocessor to use for
* performing the evaluation. If {@link IMAGE4_COPROCESSOR_HOST} is used, this
* parameter is ignored.
*
* @result
* A newly-allocated and initialized {@link image4_environment_t} object. The
* caller is responsible for disposing of this object with
* {@link image4_environment_destroy} when it is no longer needed.
*
* If insufficient resources were available to allocate the object, or if the
* host runtime does not have an allocator, NULL is returned.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT
image4_environment_t *_Nullable
image4_environment_new(
const image4_coprocessor_t *_Nullable coproc,
image4_coprocessor_handle_t handle);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_new);
/*!
* @function image4_environment_set_secure_boot
* Sets the desired secure boot level of the environment.
*
* @param nv
* The environment to manipulate.
*
* @param secure_boot
* The desired secure boot level.
*
* @discussion
* If the environment designated by the coprocessor and handle does not support
* secure boot, this is a no-op.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1
void
image4_environment_set_secure_boot(
image4_environment_t *nv,
image4_secure_boot_t secure_boot);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_set_secure_boot);
/*!
* @function image4_environment_set_nonce_domain
* Sets the nonce domain number for the environment. This value will be returned
* as the value for the coprocessor's nonce domain property during environment
* iteration (e.g. if the environment is a Cryptex1 coprocessor handle, the ndom
* property).
*
* @param nv
* The environment to modify.
*
* @param nonce_domain
* The nonce domain number to set.
*
* @discussion
* This operation does not impact trust evaluation, which always defers to the
* nonce domain signed into the manifest if one is present. It is intended to
* support two workflows:
*
* 1. Constructing a personalization request using the callbacks associated
* with {@link image4_environment_identify} by allowing all the code that
* sets the values of the TSS request to reside in the identifier
* callbacks
* 2. Related to the above, performing nonce management operations on the
* nonce slot associated by the given domain (e.g. generating a proposal
* nonce with {@link image4_environment_generate_nonce_proposal})
*
* Certain coprocessor environments recognize a nonce domain entitlement, but
* only one valid value for that entitlement (e.g.
* {@link IMAGE4_COPROCESSOR_HANDLE_CRYPTEX1_BOOT}). These environments do not
* require the nonce domain to be set; it is automatically recognized based on
* the static properties of the coprocessor.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1
void
image4_environment_set_nonce_domain(
image4_environment_t *nv,
uint32_t nonce_domain);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_set_nonce_domain);
/*!
* @function image4_environment_set_callbacks
* Sets the callbacks for an environment.
*
* @param nv
* The environment to manipulate.
*
* @param callbacks
* The callback structure.
*
* @param _ctx
* The caller-defined context to be passed to each callback.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1 OS_NONNULL2
void
image4_environment_set_callbacks(
image4_environment_t *nv,
const image4_environment_callbacks_t *callbacks,
void *_Nullable _ctx);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_set_callbacks);
/*!
* @function image4_environment_identify
* Identifies the environment and provides the identity via the callbacks
* specified in the {@link image4_environment_callbacks_t} structure set for
* the environment.
*
* @param nv
* The environment to identify.
*
* @discussion
* If no callbacks were provided, or if no identifier callbacks were set in the
* callback structure, the implementation's behavior is undefined.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1
void
image4_environment_identify(
const image4_environment_t *nv);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_identify);
/*!
* @function image4_environment_copy_nonce_digest
* Copies the digest of the specified nonce.
*
* @param nv
* The environment to query.
*
* @param digest
* Upon successful return, the digest of the live nonce for the environment. On
* failure, the contents of this structure are undefined.
*
* @result
* Upon success, zero is returned. Otherwise, the implementation may directly
* return one of the following POSIX error codes:
*
* [EPERM] The caller lacks the entitlement required to access the
* desired nonce
* [ENOTSUP] The environment does not manage a nonce for anti-replay
* [ESTALE] The nonce has been invalidated and will not be available until
* the next boot
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
errno_t
image4_environment_copy_nonce_digest(
const image4_environment_t *nv,
image4_nonce_digest_t *digest);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_copy_nonce_digest);
/*!
* @function image4_environment_roll_nonce
* Invalidates the live nonce for the environment such that a new nonce will be
* generated at the next boot.
*
* @param nv
* The environment to manipulate.
*
* @result
* Upon success, zero is returned. Otherwise, the implementation may directly
* return one of the following POSIX error codes:
*
* [EPERM] The caller lacks the entitlement required to access the
* desired nonce
* [ENOTSUP] The environment does not manage a nonce for anti-replay
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
errno_t
image4_environment_roll_nonce(
const image4_environment_t *nv);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_roll_nonce);
/*!
* @function image4_environment_generate_nonce_proposal
* Generates a nonce proposal for the environment and returns the hash of the
* proposal.
*
* @param nv
* The environment to manipulate.
*
* @param digest
* Upon successful return, the digest of the nonce proposal which was generated.
* On failure, the contents of this structure are undefined.
*
* @result
* Upon success, zero is returned. Otherwise, the implementation may directly
* return one of the following POSIX error codes:
*
* [EPERM] The caller lacks the entitlement required to manipulate the
* desired nonce
* [ENOTSUP] The environment does not manage a nonce for anti-replay
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
errno_t
image4_environment_generate_nonce_proposal(
const image4_environment_t *nv,
image4_nonce_digest_t *digest);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_generate_nonce_proposal);
/*!
* @function image4_environment_commit_nonce_proposal
* Commits the nonce proposal corresponding to the digest provided by the caller
* such that it will be accepted and live at the next boot.
*
* @param nv
* The environment to manipulate.
*
* @param digest
* The digest of the proposal to commit.
*
* @result
* Upon success, zero is returned. Otherwise, the implementation may directly
* return one of the following POSIX error codes:
*
* [EPERM] The caller lacks the entitlement required to manipulate the
* desired nonce
* [ENOTSUP] The environment does not manage a nonce for anti-replay
* [ENODEV] There is no proposal for the given nonce
* [EILSEQ] The digest provided by the caller does not correspond to the
* active proposal; this may occur if another subsystem
* generates a proposal for the environment
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
errno_t
image4_environment_commit_nonce_proposal(
const image4_environment_t *nv,
const image4_nonce_digest_t *digest);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_commit_nonce_proposal);
/*!
* @function image4_environment_get_nonce_handle
* Obtains the appropriate nonce handle to include in a signing request for the
* environment.
*
* @param nv
* The environment to query.
*
* @param handle
* Upon successful return, the handle appropriate for the signing request's
* nonce domain field. On failure, this parameter's value is undefined.
*
* @result
* Upon success, zero is returned. Otherwise, the implementation may directly
* return one of the following POSIX error codes:
*
* [ENOTSUP] The environment does not manage a nonce for anti-replay
* [ENOENT] The environment does not support identifing a nonce by its
* handle in the personalization request
*
* @discussion
* This function is not implemented and will be removed. See discussion in
* {@link image4_environment_set_nonce_handle} for guidance as to how to
* implement the relevant workflows.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
errno_t
image4_environment_get_nonce_handle(
const image4_environment_t *nv,
uint64_t *handle);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_get_nonce_handle);
/*!
* @function image4_environment_destroy
* Disposes an environment object which was created via
* {@link image4_environment_new}.
*
* @param nv
* A pointer to the environment object. Upon return, this storage will be set to
* NULL. If the object pointed to by this parameter is NULL, this is a no-op.
*
* @discussion
* If this routine is called on an environment object which was not allocated,
* it is a no-op.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1
void
image4_environment_destroy(
image4_environment_t *_Nonnull *_Nullable nv);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_environment_destroy);
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMAGE4_API_ENVIRONMENT_H

View file

@ -0,0 +1,135 @@
/*!
* @header
* Encapsulation which describes an Image4 identifier. An identifier expresses
* the four character code in a signing request as well as the constraint that
* the environment places on it.
*
* Identifiers are not created directly; they are always provided to the caller
* by other API and exist within the context of an environment.
*/
#ifndef __IMAGE4_API_IDENTIFIER_H
#define __IMAGE4_API_IDENTIFIER_H
#include <image4/image4.h>
#include <image4/types.h>
#include <image4/coprocessor.h>
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
#pragma mark Types
/*!
* @typedef image4_identifier_constraint_t
* An enumeration expressing the type of constraint the identifier places on the
* environment.
*
* @const IMAGE4_IDENTIFIER_CONSTRAINT_EQ
* The identifier must match the value in the manifest.
*
* @const IMAGE4_IDENTIFIER_CONSTRAINT_LT
* The identifier must be less than the value in the manifest.
*
* @const IMAGE4_IDENTIFIER_CONSTRAINT_LE
* The identifier must be less than or equal to the value in the manifest.
*
* @const IMAGE4_IDENTIFIER_CONSTRAINT_GT
* The identifier must be greater than the value in the manifest.
*
* @const IMAGE4_IDENTIFIER_CONSTRAINT_GE
* The identifier must be greater than or equal the value in the manifest.
*
* @const IMAGE4_IDENTIFIER_CONSTRAINT_NE
* The identifier must not be equal to the value in the manifest.
*
* @const IMAGE4_IDENTIFIER_CONSTRAINT_UN
* The identifier is not constrained at all.
*
* @const IMAGE4_IDENTIFIER_CONSTRAINT_NA
* The identifier's constraints are not known, or the identifier does not
* represent a constraint.
*/
OS_CLOSED_ENUM(image4_identifier_constraint, uint64_t,
IMAGE4_IDENTIFIER_CONSTRAINT_EQ,
IMAGE4_IDENTIFIER_CONSTRAINT_LT,
IMAGE4_IDENTIFIER_CONSTRAINT_LE,
IMAGE4_IDENTIFIER_CONSTRAINT_GT,
IMAGE4_IDENTIFIER_CONSTRAINT_GE,
IMAGE4_IDENTIFIER_CONSTRAINT_NE,
IMAGE4_IDENTIFIER_CONSTRAINT_UN,
IMAGE4_IDENTIFIER_CONSTRAINT_NA,
);
#pragma mark API
/*!
* @function image4_identifier_get_constraint
* Obtain the constraint for the identifier.
*
* @param id4
* The identifier to query.
*
* @result
* The constraint which the environment places on the identifier.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
image4_identifier_constraint_t
image4_identifier_get_constraint(const image4_identifier_t *id4);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_identifier_get_constraint);
/*!
* @function image4_identifier_get_constraint
* Obtain a C string representation of the constraint for the identifier.
*
* @param id4
* The identifier to query.
*
* @result
* The C string representation of the constraint which the identifier places on
* the environment.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
const char *
image4_identifier_get_constraint_cstr(const image4_identifier_t *id4);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_identifier_get_constraint_cstr);
/*!
* @function image4_identifier_get_fourcc
* Obtain the four character code for the identifier.
*
* @param id4
* The identifier to query.
*
* @result
* The four character code which represents the identifier in a manifest.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
uint32_t
image4_identifier_get_fourcc(const image4_identifier_t *id4);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_identifier_get_fourcc);
/*!
* @function image4_identifier_get_fourcc_cstr
* Obtain the C string representation of the four character code for the
* identifier.
*
* @param id4
* The identifier to query.
*
* @result
* The C string representation of the four character code which represents the
* identifier in a manifest.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
const char *
image4_identifier_get_fourcc_cstr(const image4_identifier_t *id4);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_identifier_get_fourcc_cstr);
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMAGE4_API_IDENTIFIER_H

View file

@ -0,0 +1,127 @@
/*!
* @header
* Umbrella header for Image4 trust evaluation API.
*/
#ifndef __IMAGE4_API_H
#define __IMAGE4_API_H
/*!
* @const IMAGE4_API_VERSION
* The API version of the library. This version will be changed in accordance
* with new API introductions so that callers may submit code to the build that
* adopts those new APIs before the APIs land by using the following pattern:
*
* #if IMAGE4_API_VERSION >= 20221230
* image4_new_api();
* #endif
*
* In this example, the library maintainer and API adopter agree on an API
* version of 20221230 ahead of time for the introduction of
* image4_new_api(). When a libdarwin with that API version is submitted, the
* project is rebuilt, and the new API becomes active.
*
* Breaking API changes will be both covered under this mechanism as well as
* individual preprocessor macros in this header that declare new behavior as
* required.
*/
#define IMAGE4_API_VERSION (20231216u)
#if __has_include(<os/base.h>)
#include <os/base.h>
#else
#include <image4/shim/base.h>
#endif
#if __has_include(<sys/types.h>)
#include <sys/types.h>
#if !defined(_ERRNO_T)
typedef int errno_t;
#endif // !defined(_ERRNO_T)
#else
#include <image4/shim/types.h>
#endif
#if __has_include(<TargetConditionals.h>)
#include <TargetConditionals.h>
#endif
#if __has_include(<os/availability.h>)
#include <os/availability.h>
#endif
#if __has_include(<sys/cdefs.h>)
#include <sys/cdefs.h>
#endif
#if !defined(__BEGIN_DECLS)
#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
#endif
#if !defined(__static_size)
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && __GNUC__
#define __static_size static
#define __static_size_const static const
#else
#define __static_size
#define __static_size_const
#endif
#endif // !defined(__static_size)
/*!
* @brief
* Pass -DIMAGE4_STRIP_AVAILABILITY=1 if the build environment is picking up a
* definition of API_AVAILABLE from somewhere, e.g. an old shim header or from
* inappropriately-injected header search paths.
*/
#if !defined(API_AVAILABLE) || IMAGE4_STRIP_AVAILABILITY
#undef API_AVAILABLE
#define API_AVAILABLE(...)
#endif
#if XNU_KERNEL_PRIVATE
#if !defined(__IMAGE4_XNU_INDIRECT)
#error "Please include <libkern/image4/dlxk.h> instead of this header"
#endif
#endif
/*!
* @const IMAGE4_API_AVAILABLE_SPRING_2024
* APIs which first became available in the Spring 2024 set of releases.
*/
#define IMAGE4_API_AVAILABLE_SPRING_2024 \
API_AVAILABLE( \
macos(14.3), \
ios(17.4), \
tvos(17.4), \
watchos(10.4), \
bridgeos(8.3))
/*!
* @const IMAGE4_XNU_AVAILABLE_DIRECT
* API symbol which is available to xnu via the dlxk mechanism.
*/
#if XNU_KERNEL_PRIVATE || IMAGE4_DLXK_AVAILABILITY
#define IMAGE4_XNU_AVAILABLE_DIRECT(_s) typedef typeof(&_s) _ ## _s ## _dlxk_t
#else
#define IMAGE4_XNU_AVAILABLE_DIRECT(_s)
#endif
/*!
* @const IMAGE4_XNU_AVAILABLE_INDIRECT
* API symbol which is accessed through a macro and is available to xnu via the
* dlxk mechanism.
*/
#if XNU_KERNEL_PRIVATE || IMAGE4_DLXK_AVAILABILITY
#define IMAGE4_XNU_AVAILABLE_INDIRECT(_s) typedef typeof(&_s) _s ## _dlxk_t
#else
#define IMAGE4_XNU_AVAILABLE_INDIRECT(_s)
#endif
#endif // __IMAGE4_API_H

View file

@ -0,0 +1,341 @@
/*
* Copyright (c) 2008-2020 Apple Inc. All rights reserved.
*
* @APPLE_APACHE_LICENSE_HEADER_START@
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @APPLE_APACHE_LICENSE_HEADER_END@
*/
#ifndef __OS_BASE__
#define __OS_BASE__
#include <sys/cdefs.h>
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#ifndef __has_include
#define __has_include(x) 0
#endif
#ifndef __has_feature
#define __has_feature(x) 0
#endif
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
#ifndef __has_extension
#define __has_extension(x) 0
#endif
#undef OS_INLINE // <sys/_types/_os_inline.h>
#if __GNUC__
#define OS_NORETURN __attribute__((__noreturn__))
#define OS_NOTHROW __attribute__((__nothrow__))
#define OS_NONNULL1 __attribute__((__nonnull__(1)))
#define OS_NONNULL2 __attribute__((__nonnull__(2)))
#define OS_NONNULL3 __attribute__((__nonnull__(3)))
#define OS_NONNULL4 __attribute__((__nonnull__(4)))
#define OS_NONNULL5 __attribute__((__nonnull__(5)))
#define OS_NONNULL6 __attribute__((__nonnull__(6)))
#define OS_NONNULL7 __attribute__((__nonnull__(7)))
#define OS_NONNULL8 __attribute__((__nonnull__(8)))
#define OS_NONNULL9 __attribute__((__nonnull__(9)))
#define OS_NONNULL10 __attribute__((__nonnull__(10)))
#define OS_NONNULL11 __attribute__((__nonnull__(11)))
#define OS_NONNULL12 __attribute__((__nonnull__(12)))
#define OS_NONNULL13 __attribute__((__nonnull__(13)))
#define OS_NONNULL14 __attribute__((__nonnull__(14)))
#define OS_NONNULL15 __attribute__((__nonnull__(15)))
#define OS_NONNULL_ALL __attribute__((__nonnull__))
#define OS_SENTINEL __attribute__((__sentinel__))
#define OS_PURE __attribute__((__pure__))
#define OS_CONST __attribute__((__const__))
#define OS_WARN_RESULT __attribute__((__warn_unused_result__))
#define OS_MALLOC __attribute__((__malloc__))
#define OS_USED __attribute__((__used__))
#define OS_UNUSED __attribute__((__unused__))
#define OS_COLD __attribute__((__cold__))
#define OS_WEAK __attribute__((__weak__))
#define OS_WEAK_IMPORT __attribute__((__weak_import__))
#define OS_NOINLINE __attribute__((__noinline__))
#define OS_ALWAYS_INLINE __attribute__((__always_inline__))
#define OS_TRANSPARENT_UNION __attribute__((__transparent_union__))
#define OS_ALIGNED(n) __attribute__((__aligned__((n))))
#define OS_FORMAT_PRINTF(x, y) __attribute__((__format__(printf,x,y)))
#define OS_EXPORT extern __attribute__((__visibility__("default")))
#define OS_INLINE static __inline__
#define OS_EXPECT(x, v) __builtin_expect((x), (v))
#else
#define OS_NORETURN
#define OS_NOTHROW
#define OS_NONNULL1
#define OS_NONNULL2
#define OS_NONNULL3
#define OS_NONNULL4
#define OS_NONNULL5
#define OS_NONNULL6
#define OS_NONNULL7
#define OS_NONNULL8
#define OS_NONNULL9
#define OS_NONNULL10
#define OS_NONNULL11
#define OS_NONNULL12
#define OS_NONNULL13
#define OS_NONNULL14
#define OS_NONNULL15
#define OS_NONNULL_ALL
#define OS_SENTINEL
#define OS_PURE
#define OS_CONST
#define OS_WARN_RESULT
#define OS_MALLOC
#define OS_USED
#define OS_UNUSED
#define OS_COLD
#define OS_WEAK
#define OS_WEAK_IMPORT
#define OS_NOINLINE
#define OS_ALWAYS_INLINE
#define OS_TRANSPARENT_UNION
#define OS_ALIGNED(n)
#define OS_FORMAT_PRINTF(x, y)
#define OS_EXPORT extern
#define OS_INLINE static inline
#define OS_EXPECT(x, v) (x)
#endif
#if __has_attribute(noescape)
#define OS_NOESCAPE __attribute__((__noescape__))
#else
#define OS_NOESCAPE
#endif
#if defined(__cplusplus) && defined(__clang__)
#define OS_FALLTHROUGH [[clang::fallthrough]]
#elif __has_attribute(fallthrough)
#define OS_FALLTHROUGH __attribute__((__fallthrough__))
#else
#define OS_FALLTHROUGH
#endif
#if __has_feature(assume_nonnull)
#define OS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
#define OS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
#else
#define OS_ASSUME_NONNULL_BEGIN
#define OS_ASSUME_NONNULL_END
#endif
#if __has_builtin(__builtin_assume)
#define OS_COMPILER_CAN_ASSUME(expr) __builtin_assume(expr)
#else
#define OS_COMPILER_CAN_ASSUME(expr) ((void)(expr))
#endif
#if __has_extension(attribute_overloadable)
#define OS_OVERLOADABLE __attribute__((__overloadable__))
#else
#define OS_OVERLOADABLE
#endif
#if __has_attribute(analyzer_suppress)
#define OS_ANALYZER_SUPPRESS(RADAR) __attribute__((analyzer_suppress))
#else
#define OS_ANALYZER_SUPPRESS(RADAR)
#endif
#if __has_attribute(enum_extensibility)
#define __OS_ENUM_ATTR __attribute__((enum_extensibility(open)))
#define __OS_ENUM_ATTR_CLOSED __attribute__((enum_extensibility(closed)))
#else
#define __OS_ENUM_ATTR
#define __OS_ENUM_ATTR_CLOSED
#endif // __has_attribute(enum_extensibility)
#if __has_attribute(flag_enum)
/*!
* Compile with -Wflag-enum and -Wassign-enum to enforce at definition and
* assignment, respectively, i.e. -Wflag-enum prevents you from creating new
* enumeration values from illegal values within the enum definition, and
* -Wassign-enum prevents you from assigning illegal values to a variable of the
* enum type.
*/
#define __OS_OPTIONS_ATTR __attribute__((flag_enum))
#else
#define __OS_OPTIONS_ATTR
#endif // __has_attribute(flag_enum)
#if __has_feature(objc_fixed_enum) || __has_extension(cxx_fixed_enum) || \
__has_extension(cxx_strong_enums)
#define OS_ENUM(_name, _type, ...) \
typedef enum : _type { __VA_ARGS__ } _name##_t
#define OS_CLOSED_ENUM(_name, _type, ...) \
typedef enum : _type { __VA_ARGS__ } __OS_ENUM_ATTR_CLOSED _name##_t
#define OS_OPTIONS(_name, _type, ...) \
typedef enum : _type { __VA_ARGS__ } __OS_ENUM_ATTR __OS_OPTIONS_ATTR _name##_t
#define OS_CLOSED_OPTIONS(_name, _type, ...) \
typedef enum : _type { __VA_ARGS__ } __OS_ENUM_ATTR_CLOSED __OS_OPTIONS_ATTR _name##_t
#else
/*!
* There is unfortunately no good way in plain C to have both fixed-type enums
* and enforcement for clang's enum_extensibility extensions. The primary goal
* of these macros is to allow you to define an enum and specify its width in a
* single statement, and for plain C that is accomplished by defining an
* anonymous enum and then separately typedef'ing the requested type name to the
* requested underlying integer type. So the type emitted actually has no
* relationship at all to the enum, and therefore while the compiler could
* enforce enum extensibility if you used the enum type, it cannot do so if you
* use the "_t" type resulting from this expression.
*
* But we still define a named enum type and decorate it appropriately for you,
* so if you really want the enum extensibility enforcement, you can use the
* enum type yourself, i.e. when compiling with a C compiler:
*
* OS_CLOSED_ENUM(my_type, uint64_t,
* FOO,
* BAR,
* BAZ,
* );
*
* my_type_t mt = 98; // legal
* enum my_type emt = 98; // illegal
*
* But be aware that the underlying enum type's width is subject only to the C
* language's guarantees -- namely that it will be compatible with int, char,
* and unsigned char. It is not safe to rely on the size of this type.
*
* When compiling in ObjC or C++, both of the above assignments are illegal.
*/
#define __OS_ENUM_C_FALLBACK(_name, _type, ...) \
typedef _type _name##_t; enum _name { __VA_ARGS__ }
#define OS_ENUM(_name, _type, ...) \
typedef _type _name##_t; enum { __VA_ARGS__ }
#define OS_CLOSED_ENUM(_name, _type, ...) \
__OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \
__OS_ENUM_ATTR_CLOSED
#define OS_OPTIONS(_name, _type, ...) \
__OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \
__OS_ENUM_ATTR __OS_OPTIONS_ATTR
#define OS_CLOSED_OPTIONS(_name, _type, ...) \
__OS_ENUM_C_FALLBACK(_name, _type, ## __VA_ARGS__) \
__OS_ENUM_ATTR_CLOSED __OS_OPTIONS_ATTR
#endif // __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
#if __has_feature(attribute_availability_swift)
// equivalent to __SWIFT_UNAVAILABLE from Availability.h
#define OS_SWIFT_UNAVAILABLE(_msg) \
__attribute__((__availability__(swift, unavailable, message=_msg)))
#else
#define OS_SWIFT_UNAVAILABLE(_msg)
#endif
#if __has_attribute(__swift_attr__)
#define OS_SWIFT_UNAVAILABLE_FROM_ASYNC(msg) \
__attribute__((__swift_attr__("@_unavailableFromAsync(message: \"" msg "\")")))
#else
#define OS_SWIFT_UNAVAILABLE_FROM_ASYNC(msg)
#endif
#if __has_attribute(swift_private)
# define OS_REFINED_FOR_SWIFT __attribute__((__swift_private__))
#else
# define OS_REFINED_FOR_SWIFT
#endif
#if __has_attribute(swift_name)
# define OS_SWIFT_NAME(_name) __attribute__((__swift_name__(#_name)))
#else
# define OS_SWIFT_NAME(_name)
#endif
#define __OS_STRINGIFY(s) #s
#define OS_STRINGIFY(s) __OS_STRINGIFY(s)
#define __OS_CONCAT(x, y) x ## y
#define OS_CONCAT(x, y) __OS_CONCAT(x, y)
#ifdef __GNUC__
#define os_prevent_tail_call_optimization() __asm__("")
#define os_is_compile_time_constant(expr) __builtin_constant_p(expr)
#define os_compiler_barrier() __asm__ __volatile__("" ::: "memory")
#else
#define os_prevent_tail_call_optimization() do { } while (0)
#define os_is_compile_time_constant(expr) 0
#define os_compiler_barrier() do { } while (0)
#endif
#if __has_attribute(not_tail_called)
#define OS_NOT_TAIL_CALLED __attribute__((__not_tail_called__))
#else
#define OS_NOT_TAIL_CALLED
#endif
typedef void (*os_function_t)(void *_Nullable);
#ifdef __BLOCKS__
/*!
* @typedef os_block_t
*
* @abstract
* Generic type for a block taking no arguments and returning no value.
*
* @discussion
* When not building with Objective-C ARC, a block object allocated on or
* copied to the heap must be released with a -[release] message or the
* Block_release() function.
*
* The declaration of a block literal allocates storage on the stack.
* Therefore, this is an invalid construct:
* <code>
* os_block_t block;
* if (x) {
* block = ^{ printf("true\n"); };
* } else {
* block = ^{ printf("false\n"); };
* }
* block(); // unsafe!!!
* </code>
*
* What is happening behind the scenes:
* <code>
* if (x) {
* struct Block __tmp_1 = ...; // setup details
* block = &__tmp_1;
* } else {
* struct Block __tmp_2 = ...; // setup details
* block = &__tmp_2;
* }
* </code>
*
* As the example demonstrates, the address of a stack variable is escaping the
* scope in which it is allocated. That is a classic C bug.
*
* Instead, the block literal must be copied to the heap with the Block_copy()
* function or by sending it a -[copy] message.
*/
typedef void (^os_block_t)(void);
#endif
#define OS_ASSUME_PTR_ABI_SINGLE_BEGIN __ASSUME_PTR_ABI_SINGLE_BEGIN
#define OS_ASSUME_PTR_ABI_SINGLE_END __ASSUME_PTR_ABI_SINGLE_END
#define OS_UNSAFE_INDEXABLE __unsafe_indexable
#define OS_HEADER_INDEXABLE __header_indexable
#define OS_COUNTED_BY(N) __counted_by(N)
#define OS_SIZED_BY(N) __sized_by(N)
#endif // __OS_BASE__

View file

@ -0,0 +1,10 @@
/*!
* @header
* Shim header to provide errno_t.
*/
#ifndef __IMAGE4_SHIM_SYS_TYPES_H
#define __IMAGE4_SHIM_SYS_TYPES_H
typedef int errno_t;
#endif // __IMAGE4_SHIM_SYS_TYPES_H

View file

@ -0,0 +1,516 @@
/*!
* @header
* Encapsulation which describes an Image4 trust object. This object can perform
* an evaluation in the context of a given environment, record properties that
* were encountered during evaluation, and deliver the evaluation result to the
* caller according to the type of evaluation being performed.
*/
#ifndef __IMAGE4_API_TRUST_H
#define __IMAGE4_API_TRUST_H
#include <image4/image4.h>
#include <image4/types.h>
#include <stdint.h>
#include <stdbool.h>
#if __has_include(<sys/types.h>)
#include <sys/types.h>
#else
typedef int errno_t;
#endif
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
#pragma mark Supporting Types
/*!
* @typedef image4_trust_flags_t
* Flags that may be provided to influence the behavior of an
* {@link image4_trust_t} object.
*
* @const IMAGE4_TRUST_FLAG_INIT
* No flags set. This value is suitable for initialization purposes.
*
* @const IMAGE4_TRUST_FLAG_VIOLATION_PANIC
* Upon encountering a violation during trust evaluation, the implementation
* should abort the current context.
*/
OS_CLOSED_OPTIONS(image4_trust_flags, uint64_t,
IMAGE4_TRUST_FLAG_INIT = 0,
IMAGE4_TRUST_FLAG_VIOLATION_PANIC = (1 << 0),
);
/*!
* @typedef image4_trust_section_t
* An enumeration of property sections in an Image4 manifest or object. Note
* that this is not strictly aligned with the concept of a "section" as defined
* in the Image4 specification.
*
* @const IMAGE4_TRUST_SECTION_CERTIFICATE
* The certificate properties within the manifest section.
*
* @const IMAGE4_TRUST_SECTION_MANIFEST
* The top-level properties in the manifest section.
*
* @const IMAGE4_TRUST_SECTION_OBJECT
* The properties associated with a particular object in the manifest section.
*
* @const IMAGE4_TRUST_SECTION_RESTORE_INFO
* The top-level properties in the RestoreInfo section. The RestoreInfo section
* is only recognized by the implementation when the trust object has been
* initialized with an IMG4 object that contains an IM4R section.
*
* This constant first became available in API version 20231103.
*
* @const IMAGE4_TRUST_SECTION_PAYLOAD_PROPERTIES
* The properties associated with the payload that is associated with the trust
* object, either by initializing the object with an IMG4 object, or by setting
* a payload with {@link image4_trust_set_payload}.
*
* This constant first became available in API version 20231103.
*/
OS_CLOSED_ENUM(image4_trust_section, uint64_t,
IMAGE4_TRUST_SECTION_CERTIFICATE,
IMAGE4_TRUST_SECTION_MANIFEST,
IMAGE4_TRUST_SECTION_OBJECT,
IMAGE4_TRUST_SECTION_RESTORE_INFO,
IMAGE4_TRUST_SECTION_PAYLOAD_PROPERTIES,
_IMAGE4_TRUST_SECTION_CNT,
);
/*!
* @typedef image4_trust_evaluation_result_t
* A callback for the result of a trust evaluation.
*
* @param trst
* The trust object.
*
* @param result
* Upon success, the prescribed payload resulting from the type of trust
* evaluation. If the trust evaluation type does not deliver a payload, or the
* trust evaluation failed, NULL will be passed.
*
* @param result_len
* The length of the buffer referenced by {@link payload}. If {@link payload} is
* NULL, zero will be passed.
*
* @param error
* A POSIX error code describing the result of the trust evaluation. Upon
* success, zero will be passed.
*
* @param context
* The caller-provided context pointer. If no context pointer was set, NULL will
* be passed.
*/
typedef void (*image4_trust_evaluation_result_t)(
const image4_trust_t *trst,
const void *_Nullable result,
size_t result_len,
errno_t error,
void *_Nullable context
);
/*!
* @const IMAGE4_TRUST_STRUCT_VERSION
* The version of the {@link image4_trust_t} structure supported by the
* implementation.
*/
#define IMAGE4_TRUST_STRUCT_VERSION (0u)
/*!
* @header image4_trust_storage_t
* An opaque structure which is guaranteed to be large enough to accommodate an
* {@link image4_trust_t}.
*
* @field __opaque
* The opaque storage.
*
* @discussion
* The size of this object was set in API version 20231103.
*/
typedef struct _image4_trust_storage {
uint8_t __opaque[1920];
} image4_trust_storage_t;
/*!
* @const IMAGE4_TRUST_STORAGE_INIT
* Initializer for a {@link image4_trust_storage_t} object.
*/
#define IMAGE4_TRUST_STORAGE_INIT (image4_trust_storage_t){ \
.__opaque = { 0x00 }, \
}
#pragma mark API
/*!
* @function image4_trust_init
* Convert a {@link image4_trust_storage_t} to an initialized
* {@link image4_trust_t} object.
*
* @param storage
* The storage structure.
*
* @param environment
* The environment in which the trust evaluation should be performed.
*
* @param evaluation
* The trust evaluation type that should be performed.
*
* @param manifest
* A pointer to the Image4 manifest bytes. This buffer may refer to a stitched
* manifest and payload object, in which case the implementation will extract
* the manifest portion.
*
* These bytes are not copied into any implementation storage, and the caller is
* responsible for ensuring that this memory remains valid for the duration of
* the trust object's use.
*
* @param manifest_len
* The length of the buffer referenced by {@link manifest}.
*
* @param flags
* Flags to influence the behavior of the resulting trust object.
*
* @result
* An initialized {@link image4_trust_t} object.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3 OS_NONNULL4
image4_trust_t *
_image4_trust_init(
image4_trust_storage_t *storage,
const image4_environment_t *environment,
const image4_trust_evaluation_t *evaluation,
const void *__sized_by(manifest_len) manifest,
size_t manifest_len,
image4_trust_flags_t flags,
image4_struct_version_t v);
#define image4_trust_init(_storage, _environment, _evaluation, \
_manifest, _manifest_len, _flags) \
_image4_trust_init( \
(_storage), \
(_environment), \
(_evaluation), \
(_manifest), \
(_manifest_len), \
(_flags), \
IMAGE4_TRUST_STRUCT_VERSION)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_trust_init);
/*!
* @function image4_trust_new
* Allocates a trust object.
*
* @param nv
* The environment in which the trust evaluation should be performed.
*
* @param eval
* The trust evaluation type that should be performed.
*
* @param manifest
* A pointer to the Image4 manifest bytes. This buffer may refer to a stitched
* manifest and payload object, in which case the implementation will extract
* the manifest portion.
*
* These bytes are not copied into any implementation storage, and the caller is
* responsible for ensuring that this memory remains valid for the duration of
* the trust object's use.
*
* @param manifest_len
* The length of the buffer referenced by {@link manifest}.
*
* @param flags
* Flags to influence the behavior of the resulting trust object.
*
* @result
* A newly-allocated and initialized {@link image4_trust_t} object. The caller
* is responsible for disposing of this object with {@link image4_trust_destroy}
* when it is no longer needed.
*
* If insufficient resources were available to allocate the object, or if the
* host runtime does not have an allocator, NULL is returned.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2 OS_NONNULL3
image4_trust_t *_Nullable
image4_trust_new(
const image4_environment_t *nv,
const image4_trust_evaluation_t *eval,
const void *__sized_by(manifest_len) manifest,
size_t manifest_len,
image4_trust_flags_t flags);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_new);
/*!
* @function image4_trust_set_payload
* Sets the payload to be used during the trust evaluation.
*
* @param trst
* The trust object.
*
* @param type
* The four-character code of the payload.
*
* @param bytes
* A pointer to the payload bytes to authenticate during trust evaluation. This
* buffer may refer to a stitched manifest and payload object, in which case the
* implementation will extract the payload portion.
*
* If the buffer does not refer to either a valid Image4 manifest or payload,
* the implementation will conclude that it is a bare Image4 payload -- that is,
* a payload which is not Image4-wrapped.
*
* These bytes are not copied into any implementation storage, and the caller is
* responsible for ensuring that this memory remains valid for the duration of
* the trust object's use.
*
* @param len
* The length of the buffer referenced by {@link bytes}.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1 OS_NONNULL3
void
image4_trust_set_payload(
image4_trust_t *trst,
uint32_t type,
const void *__sized_by(len) bytes,
size_t len);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_set_payload);
/*!
* @function image4_trust_set_booter
* Establish a link between the trust object and another trust object
* representing a previous stage of boot, securing it to that stage of boot.
* This may be called multiple times. Successive calls secure the previously-
* specified booter stage to the newly-specified booter stage, establishing a
* chain of trust from the last stage to the first stage.
*
* @param trst
* The trust object. This object must have been created with one of the
* following trust evaluation types:
*
* - {@link IMAGE4_TRUST_EVALUATION_PREFLIGHT}
* - {@link IMAGE4_TRUST_EVALUATION_SIGN}
*
* @param booter
* The trust object representing the previous stage of boot for {@link trst}.
* This object must have been created with the
* {@link IMAGE4_TRUST_EVALUATION_BOOT} trust evaluation type.
*
* This object is not copied into any implementation storage, and the caller is
* responsible for ensuring that it remains valid for the duration of the trust
* object's use.
*
* @discussion
* Trust objects with booter stages cannot be used to execute firmware because
* they are only intended to simulate a boot by replicating side effects of
* previous evaluations into the ultimate environment used by the trust object.
*
* In order to execute firmware, the environment must be consistent with the
* requirements of the manifest without modifications being required.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1 OS_NONNULL2
void
image4_trust_set_booter(
image4_trust_t *trst,
const image4_trust_t *booter);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_set_booter);
/*!
* @function image4_trust_record_property_bool
* Records the specified Boolean value into caller-provided storage.
*
* @param trst
* The trust object.
*
* @param type
* The type of property to be recorded (currently either manifest or object).
*
* @param tag
* The four character code of the property to capture.
*
* @param vp
* A pointer to the storage where the value should be written.
*
* @param vpp
* A pointer to storage where a pointer to the value should be written. This
* allows the caller to know whether the property was encountered during the
* trust evaluation at all. If the property was encountered, the storage
* referred to by this pointer will hold the same pointer given in the
* {@link vp} parameter.
*
* If the property was not encountered during trust evaluation, the contents of
* this storage are undefined. The caller should initialize the storage to a
* reasonable default.
*
* This may be NULL.
*
* @discussion
* If the property represented a constraint which was not satisfied, the
* implementation will not record its value.
*
* If the property associated with the given tag is present, but is not a
* Boolean, the implementation will not record its value.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1 OS_NONNULL4
void
image4_trust_record_property_bool(
image4_trust_t *trst,
image4_trust_section_t type,
uint32_t tag,
bool *vp,
const bool *_Nullable *_Nullable vpp);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_record_property_bool);
/*!
* @function image4_trust_record_property_integer
* Records the specified unsigned integer value into caller-provided storage.
*
* @param trst
* The trust object.
*
* @param type
* The type of property to be recorded (currently either manifest or object).
*
* @param tag
* The four character code of the property to capture.
*
* @param vp
* A pointer to the storage where the value should be written.
*
* @param vpp
* A pointer to storage where a pointer to the value should be written. This
* allows the caller to know whether the property was encountered during the
* trust evaluation at all. If the property was encountered, the storage
* referred to by this pointer will hold the same pointer given in the
* {@link vp} parameter.
*
* If the property was not encountered during trust evaluation, the contents of
* this storage are undefined. The caller should initialize the storage to a
* reasonable default.
*
* This may be NULL.
*
* @discussion
* For boring implementation reasons, all integer properties are expressed as
* 64-bit unsigned integers. The caller is responsible for enforcing boundaries
* on the value recorded.
*
* If the property represented a constraint which was not satisfied, the
* implementation will not record its value.
*
* If the property associated with the given tag is present, but is not an
* integer, the implementation will not record its value.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1 OS_NONNULL4
void
image4_trust_record_property_integer(
image4_trust_t *trst,
image4_trust_section_t type,
uint32_t tag,
uint64_t *vp,
const uint64_t *_Nullable *_Nullable vpp);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_record_property_integer);
/*!
* @function image4_trust_record_property_data
* Records a pointer to the specified octet string value into caller-provided
* storage.
*
* @param trst
* The trust object.
*
* @param type
* The type of property to be recorded (currently either manifest or object).
*
* @param tag
* The four character code of the property to capture.
*
* @param vp
* A pointer to the storage where the value should be written. The storage
* referenced by this pointer ultimately refers to the caller-provided memory
* which contains the Image4 manifest, and therefore its lifetime is tied to the
* caller's management of that storage.
*
* If the property was not encountered during trust evaluation, the contents of
* this storage are undefined. The caller should initialize the storage to a
* reasonable default.
*
* @param vp_len
* A pointer to the storage where the length of the octet string should be
* written.
*
* @discussion
* If the property represented a constraint which was not satisfied, the
* implementation will not record its value.
*
* If the property associated with the given tag is present, but is not an octet
* string, the implementation will not record its value.
*
* Properties which are intended to be used as C strings are represented in the
* manifest as simple octet strings which may or may not be null-terminated. The
* caller should take care to ensure null termination when the data is used,
* e.g. by copying the data into a local buffer using strlcpy(3).
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1 OS_NONNULL4 OS_NONNULL5
void
image4_trust_record_property_data(
image4_trust_t *trst,
image4_trust_section_t type,
uint32_t tag,
const void *_Nullable *_Nonnull vp,
size_t *vp_len);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_record_property_data);
/*!
* @function image4_trust_evaluate
* Perform the trust evaluation.
*
* @param trst
* The trust object.
*
* @param _ctx
* A context parameter to be delivered to the result callback.
*
* @param result
* The callback to invoke with the result of the trust evaluation. This callback
* is called directly inline from the implementation and must not re-enter the
* calling scope.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1 OS_NONNULL3
void
image4_trust_evaluate(
const image4_trust_t *trst,
void *_Nullable _ctx,
image4_trust_evaluation_result_t result);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_evaluate);
/*!
* @function image4_trust_destroy
* Disposes a trust object which was created via {@link image4_trust_new}.
*
* @param nv
* A pointer to the trust object. Upon return, this storage will be set to NULL.
* If the object pointed to by this parameter is NULL, this is a no-op.
*
* @discussion
* If this routine is called on an environment object which was not allocated,
* it is a no-op.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT OS_NONNULL1
void
image4_trust_destroy(
image4_trust_t *_Nonnull *_Nullable trst);
IMAGE4_XNU_AVAILABLE_DIRECT(image4_trust_destroy);
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMAGE4_API_TRUST_H

View file

@ -0,0 +1,111 @@
/*!
* @header
* Encapsulation which describes an Image4 trust evaluation procedure. The type
* of procedure impacts the result delivered to the
* {@link image4_trust_evaluation_result_t}.
*
* All trust evaluations require a manifest to be present in the trust object.
*/
#ifndef __IMAGE4_API_TRUST_EVALUATION_H
#define __IMAGE4_API_TRUST_EVALUATION_H
#include <image4/image4.h>
#include <image4/types.h>
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @const IMAGE4_TRUST_EVALUATION_EXEC
* The trust evaluation is intended to execute firmware in the designated
* environment. This is to be used for either first- or second-stage boots.
*
* This type of trust evaluation requires a payload.
*
* @section Trust Evaluation Result
* Upon successful evaluation, the result is a pointer to the unwrapped Image4
* payload bytes.
*
* @discussion
* This trust evaluation is supported on all targets.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT
const image4_trust_evaluation_t _image4_trust_evaluation_exec;
#define IMAGE4_TRUST_EVALUATION_EXEC (&_image4_trust_evaluation_exec)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_trust_evaluation_exec);
/*!
* @const IMAGE4_TRUST_EVALUATION_PREFLIGHT
* The trust evaluation is intended to preflight a manifest to verify that it is
* likely to be accepted during a boot trust evaluation in the future. This is
* a best effort evaluation, and depending on the environment, certain
* enforcement policies may be relaxed due to the relevant information not being
* available.
*
* This type of trust evaluation does not require a payload.
*
* @section Trust Evaluation Result
* The result is an error code indicating whether the manifest is likely to be
* accepted by the environment.
*
* @discussion
* This type of trust evaluation is not supported on all targets.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT
const image4_trust_evaluation_t _image4_trust_evaluation_preflight;
#define IMAGE4_TRUST_EVALUATION_PREFLIGHT (&_image4_trust_evaluation_preflight)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_trust_evaluation_preflight);
/*!
* @const IMAGE4_TRUST_EVALUATION_SIGN
* The trust evaluation is intended to facilitate counter-signing the manifest.
*
* @section Trust Evaluation Result
* Upon successful evaluation, the result is a pointer to the digest of the
* manifest. The digest is computed using the algorithm specified by the
* environment.
*
* @discussion
* This type of trust evaluation is not supported on all targets.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT
const image4_trust_evaluation_t _image4_trust_evaluation_sign;
#define IMAGE4_TRUST_EVALUATION_SIGN (&_image4_trust_evaluation_sign)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_trust_evaluation_sign);
/*!
* @const IMAGE4_TRUST_EVALUATION_BOOT
* The trust evaluation is intended to bootstrap a subsequent trust evaluation
* in a chain of trust. The ultimate purpose of the chain of trust must be to
* either preflight a manifest or sign it.
*
* This type of trust evaluation does not require a payload.
*
* @section Trust Evaluation Result
* This type of trust evaluation is not intended to be performed directly by way
* of {@link image4_trust_evaluate}. It is instead intended to create a trust
* object which can be used as a previous stage of boot for another trust object
* by way of {@link image4_trust_set_booter}.
*
* However, if the caller wishes to perform a boot trust evaluation directly,
* then the trust evaluation result equivalent to that of
* {@link IMAGE4_TRUST_EVALUATION_SIGN}.
*
* @discussion
* This trust evaluation is supported on all targets.
*/
IMAGE4_API_AVAILABLE_SPRING_2024
OS_EXPORT
const image4_trust_evaluation_t _image4_trust_evaluation_boot;
#define IMAGE4_TRUST_EVALUATION_BOOT (&_image4_trust_evaluation_boot)
IMAGE4_XNU_AVAILABLE_INDIRECT(_image4_trust_evaluation_boot);
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMAGE4_API_TRUST_EVALUATION_H

View file

@ -0,0 +1,206 @@
/*!
* @header
* Common types shared across the Image4 trust evaluation API.
*/
#ifndef __IMAGE4_API_TYPES_H
#define __IMAGE4_API_TYPES_H
#include <image4/image4.h>
#include <stdint.h>
#include <stddef.h>
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
#pragma mark Supporting Types
/*!
* @typedef image4_struct_version_t
* The version of a structure in the API.
*/
typedef uint16_t image4_struct_version_t;
#pragma mark Supporting Types
/*!
* @typedef image4_coprocessor_handle_t
* A handle which specifies a particular execution environment within a
* coprocessor.
*/
typedef uint64_t image4_coprocessor_handle_t;
/*!
* @const IMAGE4_COPROCESSOR_HANDLE_NULL
* An coprocessor handle which is invalid for all coprocessors. This constant is
* suitable for initialization purposes only.
*/
#define IMAGE4_COPROCESSOR_HANDLE_NULL ((image4_coprocessor_handle_t)0xffff)
/*!
* @typedef image4_secure_boot_t
* An enumeration of secure boot levels.
*
* @const IMAGE4_SECURE_BOOT_FULL
* Secure Boot will only accept a live, personalized manifest.
*
* @const IMAGE4_SECURE_BOOT_REDUCED
* Secure Boot will only accept a globally-signed manifest whose lifetime is not
* entangled with the individual silicon instance. The manifest's lifetime may
* be statically constrained in other ways, but the device cannot unilaterally
* host the manifest without a software change.
*
* @const IMAGE4_SECURE_BOOT_LEAST
* Secure Boot will accept any Apple-signed manifest, and the manifest will not
* be meaningfully enforced.
*
* @const IMAGE4_SECURE_BOOT_NONE
* Secure Boot does not meaningfully exist.
*/
OS_CLOSED_ENUM(image4_secure_boot, uint64_t,
IMAGE4_SECURE_BOOT_FULL,
IMAGE4_SECURE_BOOT_REDUCED,
IMAGE4_SECURE_BOOT_LEAST,
IMAGE4_SECURE_BOOT_NONE,
_IMAGE4_SECURE_BOOT_CNT,
);
/*!
* @function image4_secure_boot_check
* Checks the secure boot level to ensure that it represents a valid, known
* secure boot configuration.
*
* @param sb
* The secure boot level.
*
* @result
* If the {@link sb} is a valid secure boot level, zero is returned. Otherwise,
* a non-zero value is returned.
*/
OS_ALWAYS_INLINE OS_WARN_RESULT
static inline int
image4_secure_boot_check(image4_secure_boot_t sb)
{
if (sb > _IMAGE4_SECURE_BOOT_CNT) {
__builtin_trap();
}
if (sb == _IMAGE4_SECURE_BOOT_CNT) {
return 1;
}
return 0;
}
/*!
* @const IMAGE4_NONCE_MAX_LEN
* The maximum size of a boot nonce.
*/
#define IMAGE4_NONCE_MAX_LEN (16u)
/*!
* @const IMAGE4_NONCE_DIGEST_STRUCT_VERSION
* The version of the {@link image4_nonce_digest_t} structure supported by the
* implementation.
*/
#define IMAGE4_NONCE_DIGEST_STRUCT_VERSION (0u)
/*!
* @const IMAGE4_NONCE_DIGEST_MAX_LEN
* The maximum size of a nonce digest.
*/
#define IMAGE4_NONCE_DIGEST_MAX_LEN (64u)
/*!
* @typedef image4_nonce_digest_t
* A structure representing a nonce digest.
*
* @field nd_version
* The version of the structure. Initialize to
* {@link IMAGE4_NONCE_DIGEST_STRUCT_VERSION}.
*
* @field nd_length
* The length of the digest.
*
* @field nd_bytes
* The digest bytes.
*/
typedef struct _image4_nonce_digest {
image4_struct_version_t nd_version;
size_t nd_length;
uint8_t nd_bytes[IMAGE4_NONCE_DIGEST_MAX_LEN];
} image4_nonce_digest_t;
/*!
* @const IMAGE4_NONCE_DIGEST_INIT
* Initializer for an {@link image4_nonce_digest_t} structure.
*/
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#define IMAGE4_NONCE_DIGEST_INIT (image4_nonce_digest_t){ \
.nd_version = IMAGE4_NONCE_DIGEST_STRUCT_VERSION, \
.nd_length = 0, \
.nd_bytes = { \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
}, \
}
#elif defined(__cplusplus) && __cplusplus >= 201103L
#define IMAGE4_NONCE_DIGEST_INIT (image4_nonce_digest_t {\
IMAGE4_NONCE_DIGEST_STRUCT_VERSION, \
0, \
{ \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
}, \
})
#elif defined(__cplusplus)
#define IMAGE4_NONCE_DIGEST_INIT (image4_nonce_digest_t(\
(image4_nonce_digest_t){ \
IMAGE4_NONCE_DIGEST_STRUCT_VERSION, \
0, \
{ \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
}, \
} \
))
#else
#define IMAGE4_NONCE_DIGEST_INIT { \
IMAGE4_NONCE_DIGEST_STRUCT_VERSION, \
0, \
{ \
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, \
}, \
}
#endif
#pragma mark API Objects
/*!
* @typedef image4_coprocessor_t
* An opaque structure representing a coprocessor.
*/
typedef struct _image4_coprocessor image4_coprocessor_t;
/*!
* @typedef image4_environment_t
* An opaque structure representing an Image4 trust evaluation environment.
*/
typedef struct _image4_environment image4_environment_t;
/*!
* @typedef image4_identifier_t
* An opaque structure representing an Image4 identifier.
*/
typedef struct _image4_identifier image4_identifier_t;
/*!
* @typedef image4_trust_evaluation_t
* An opaque structure representing an Image4 trust evaluation.
*/
typedef struct _image4_trust_evaluation image4_trust_evaluation_t;
/*!
* @typedef image4_trust_t
* An opaque structure representing an Image4 trust object which performs
* evaluations.
*/
typedef struct _image4_trust image4_trust_t;
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMAGE4_API_TYPES_H

View file

@ -0,0 +1,82 @@
/*!
* @header
* xnu-specific interfaces. These are hacks that only exist because xnu doesn't
* like linking static libraries, and we have a pre-existing contract for how to
* export our interfaces to xnu.
*/
#ifndef __IMG4_4XNU_H
#define __IMG4_4XNU_H
#ifndef __IMG4_INDIRECT
#error "Please #include <img4/firmware.h> instead of this file directly"
#endif // __IMG4_INDIRECT
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @function img4_get_manifest
* Returns a buffer representing the Image4 manifest bytes within the given DER
* blob.
*
* @param buff
* The buffer to examine for the Image4 manifest.
*
* @param len
* The length of {@link buff}.
*
* @param buff_storage
* Upon successful return, a buffer object which will contain a pointer to and
* the length of the Image4 manifest.
*
* @result
* Upon success, {@link buff_storage} is returned. If the DER blob contains no
* Image4 manifest, then NULL is returned.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211105
OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3
const img4_buff_t *
img4_get_manifest(const void *__sized_by(len) buff, size_t len,
img4_buff_t *buff_storage);
#else
#define img4_get_manifest(...) \
(img4if->i4if_v15.get_manifest(__VA_ARGS__))
#endif
/*!
* @function img4_get_payload
* Returns a buffer representing the Image4 payload bytes within the given DER
* blob.
*
* @param buff
* The buffer to examine for the Image4 payload.
*
* @param len
* The length of {@link buff}.
*
* @param buff_storage
* Upon successful return, a buffer object which will contain a pointer to and
* the length of the Image4 manifest.
*
* @result
* Upon success, {@link buff_storage} is returned. If the DER blob contains no
* Image4 payload, then NULL is returned.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211105
OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL3
const img4_buff_t *
img4_get_payload(const void *__sized_by(len) buff, size_t len,
img4_buff_t *buff_storage);
#else
#define img4_get_payload(...) \
(img4if->i4if_v15.get_payload(__VA_ARGS__))
#endif
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMG4_4XNU_H

View file

@ -0,0 +1,146 @@
/*!
* @header
* API definitions.
*/
#ifndef __IMG4_API_H
#define __IMG4_API_H
#ifndef __IMG4_INDIRECT
#error "Please #include <img4/firmware.h> instead of this file directly"
#endif // __IMG4_INDIRECT
#include <img4/shim.h>
/*!
* @const IMG4_API_VERSION
* The API version of the library. This version will be changed in accordance
* with new API introductions so that callers may submit code to the build that
* adopts those new APIs before the APIs land by using the following pattern:
*
* #if IMG4_API_VERSION >= 20180424
* img4_new_api();
* #endif
*
* In this example, the library maintainer and API adopter agree on an API
* version of 20180424 ahead of time for the introduction of
* img4_new_api(). When a libdarwin with that API version is submitted, the
* project is rebuilt, and the new API becomes active.
*
* Breaking API changes will be both covered under this mechanism as well as
* individual preprocessor macros in this header that declare new behavior as
* required.
*
* @note
* For a period of time, the API version was incorrectly defined as 20212105
* when it should have been 20210521. Avoid version comparisons across that
* version epoch.
*/
#define IMG4_API_VERSION (20221202u)
#if IMG4_TARGET_DARWIN
#define IMG4_API_AVAILABLE_FALL_2018 \
API_AVAILABLE( \
macos(10.15), \
ios(12.0), \
tvos(12.0), \
watchos(5.0))
#define IMG4_API_DEPRECATED_FALL_2018 \
API_DEPRECATED_WITH_REPLACEMENT( \
"img4_firmware_t", \
macos(10.15, 11.0), \
ios(12.2, 14.0), \
tvos(12.2, 14.0), \
watchos(5.2, 7.0))
#define IMG4_API_AVAILABLE_SPRING_2019 \
API_AVAILABLE(\
macos(10.15), \
ios(12.2), \
tvos(12.2), \
watchos(5.2))
#define IMG4_API_AVAILABLE_FALL_2020 \
API_AVAILABLE( \
macos(11.0), \
ios(14.0), \
tvos(14.0), \
watchos(7.0), \
bridgeos(5.0))
#define IMG4_API_AVAILABLE_FALL_2021 \
API_AVAILABLE( \
macos(12.0), \
ios(15.0), \
tvos(15.0), \
watchos(8.0), \
bridgeos(6.0))
#define IMG4_API_AVAILABLE_FALL_2021_B \
API_AVAILABLE( \
macos(12.1), \
ios(15.1), \
tvos(15.1), \
watchos(8.1), \
bridgeos(6.1))
#define IMG4_API_AVAILABLE_FALL_2022 \
API_AVAILABLE( \
macos(13.0), \
ios(16.0), \
tvos(16.0), \
watchos(9.0), \
bridgeos(7.0))
#define IMG4_API_AVAILABLE_SPRING_2023 \
API_AVAILABLE( \
macos(13.3), \
ios(16.4), \
tvos(16.4), \
watchos(9.4), \
bridgeos(7.4))
#else
#define IMG4_API_AVAILABLE_FALL_2018
#define IMG4_API_DEPRECATED_FALL_2018
#define IMG4_API_AVAILABLE_SPRING_2019
#define IMG4_API_AVAILABLE_FALL_2020
#define IMG4_API_AVAILABLE_FALL_2021
#define IMG4_API_AVAILABLE_FALL_2021_B
#define IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_SPRING_2023
#endif
#define IMG4_API_AVAILABLE_20180112 IMG4_API_AVAILABLE_FALL_2018
#define IMG4_API_AVAILABLE_20181106 IMG4_API_AVAILABLE_SPRING_2019
#define IMG4_API_AVAILABLE_20200508 IMG4_API_AVAILABLE_FALL_2020
#define IMG4_API_AVAILABLE_20200608 IMG4_API_AVAILABLE_FALL_2020
#define IMG4_API_AVAILABLE_20200724 IMG4_API_AVAILABLE_FALL_2020
#define IMG4_API_AVAILABLE_20210113 IMG4_API_AVAILABLE_FALL_2021
#define IMG4_API_AVAILABLE_20210205 IMG4_API_AVAILABLE_FALL_2021
#define IMG4_API_AVAILABLE_20210226 IMG4_API_AVAILABLE_FALL_2021
#define IMG4_API_AVAILABLE_20210305 IMG4_API_AVAILABLE_FALL_2021
#define IMG4_API_AVAILABLE_20210521 IMG4_API_AVAILABLE_FALL_2021
#define IMG4_API_AVAILABLE_20210624 IMG4_API_AVAILABLE_FALL_2021
#define IMG4_API_AVAILABLE_20210731 IMG4_API_AVAILABLE_FALL_2021_B
#define IMG4_API_AVAILABLE_20211105 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20211112 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20211119 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20211126 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20211224 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20220128 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20220322 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20220401 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20220513 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20220711 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20220714 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20220715 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20220912 IMG4_API_AVAILABLE_FALL_2022
#define IMG4_API_AVAILABLE_20220915 IMG4_API_AVAILABLE_SPRING_2023
#define IMG4_API_AVAILABLE_20221202 IMG4_API_AVAILABLE_SPRING_2023
/*!
* @typedef img4_struct_version_t
* A type describing the version of a structure in the library.
*/
IMG4_API_AVAILABLE_20180112
typedef uint16_t img4_struct_version_t;
#endif // __IMG4_API_H

View file

@ -0,0 +1,526 @@
/*!
* @header
* Supported chip environments.
*/
#ifndef __IMG4_CHIP_H
#define __IMG4_CHIP_H
#ifndef __IMG4_INDIRECT
#error "Please #include <img4/firmware.h> instead of this file directly"
#endif // __IMG4_INDIRECT
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @typedef img4_chip_select_array_t
* A type representing a list of chips from which the implementation may select.
*/
IMG4_API_AVAILABLE_20200724
typedef const img4_chip_t *_Nullable const *img4_chip_select_array_t;
/*!
* @const IMG4_CHIP_INSTANCE_STRUCT_VERSION
* The version of the {@link img4_chip_instance_t} supported by the
* implementation.
*/
#define IMG4_CHIP_INSTANCE_STRUCT_VERSION (6u)
/*!
* @typedef img4_chip_instance_omit_t
* A bitfield describing omitted identifiers from a chip instance.
*
* @const IMG4_CHIP_INSTANCE_OMIT_CEPO
* The chip instance has no epoch.
*
* @const IMG4_CHIP_INSTANCE_OMIT_BORD
* The chip instance has no board identifier.
*
* @const IMG4_CHIP_INSTANCE_OMIT_CHIP
* The chip instance has no chip identifier.
*
* @const IMG4_CHIP_INSTANCE_OMIT_SDOM
* The chip instance has no security domain.
*
* @const IMG4_CHIP_INSTANCE_OMIT_ECID
* The chip instance has no unique chip identifier.
*
* @const IMG4_CHIP_INSTANCE_OMIT_CPRO
* The chip instance has no certificate production status.
*
* @const IMG4_CHIP_INSTANCE_OMIT_CSEC
* The chip instance has no certificate security mode.
*
* @const IMG4_CHIP_INSTANCE_OMIT_EPRO
* The chip instance has no effective production status.
*
* @const IMG4_CHIP_INSTANCE_OMIT_ESEC
* The chip instance has no effective security mode.
*
* @const IMG4_CHIP_INSTANCE_OMIT_IUOU
* The chip instance has no internal-use-only-unit property.
*
* @const IMG4_CHIP_INSTANCE_OMIT_RSCH
* The chip instance has no research fusing state.
*
* @const IMG4_CHIP_INSTANCE_OMIT_EUOU
* The chip instance has no engineering-use-only-unit property.
*
* @const IMG4_CHIP_INSTANCE_OMIT_ESDM
* The chip instance has no extended security domain property.
*
* @const IMG4_CHIP_INSTANCE_OMIT_FPGT
* The chip instance has no factory pre-release global trust property.
*
* @const IMG4_CHIP_INSTANCE_OMIT_UDID
* The chip instance has no universal device identifier property.
*
* @const IMG4_CHIP_INSTANCE_OMIT_FCHP
* The chip instance has no cryptex chip identifier property.
*
* @const IMG4_CHIP_INSTANCE_OMIT_TYPE
* The chip instance has no cryptex type identifier property.
*
* @const IMG4_CHIP_INSTANCE_OMIT_STYP
* The chip instance has no cryptex subtype identifier property.
*
* @const IMG4_CHIP_INSTANCE_OMIT_CLAS
* The chip instance has no product class property.
*/
OS_CLOSED_OPTIONS(img4_chip_instance_omit, uint64_t,
IMG4_CHIP_INSTANCE_OMIT_CEPO = (1 << 0),
IMG4_CHIP_INSTANCE_OMIT_BORD = (1 << 1),
IMG4_CHIP_INSTANCE_OMIT_CHIP = (1 << 2),
IMG4_CHIP_INSTANCE_OMIT_SDOM = (1 << 3),
IMG4_CHIP_INSTANCE_OMIT_ECID = (1 << 4),
IMG4_CHIP_INSTANCE_OMIT_CPRO = (1 << 5),
IMG4_CHIP_INSTANCE_OMIT_CSEC = (1 << 6),
IMG4_CHIP_INSTANCE_OMIT_EPRO = (1 << 7),
IMG4_CHIP_INSTANCE_OMIT_ESEC = (1 << 8),
IMG4_CHIP_INSTANCE_OMIT_IUOU = (1 << 9),
IMG4_CHIP_INSTANCE_OMIT_RSCH = (1 << 10),
IMG4_CHIP_INSTANCE_OMIT_EUOU = (1 << 11),
IMG4_CHIP_INSTANCE_OMIT_ESDM = (1 << 12),
IMG4_CHIP_INSTANCE_OMIT_FPGT = (1 << 13),
IMG4_CHIP_INSTANCE_OMIT_UDID = (1 << 14),
IMG4_CHIP_INSTANCE_OMIT_FCHP = (1 << 15),
IMG4_CHIP_INSTANCE_OMIT_TYPE = (1 << 16),
IMG4_CHIP_INSTANCE_OMIT_STYP = (1 << 17),
IMG4_CHIP_INSTANCE_OMIT_CLAS = (1 << 18),
);
/*!
* @typedef img4_chip_instance_t
* An structure describing an instance of a chip.
*
* @field chid_version
* The version of the structure. Initialize to
* {@link IMG4_CHIP_INSTANCE_STRUCT_VERSION}.
*
* @field chid_chip_family
* The chip family of which this is an instance.
*
* @field chid_omit
* The identifiers which are absent from the chip instance.
*
* @field chid_cepo
* The certificate epoch of the chip instance.
*
* @field chid_bord
* The board identifier of the chip instance.
*
* @field chid_chip
* The chip identifier of the chip instance.
*
* @field chid_sdom
* The security domain of the chip instance.
*
* @field chid_ecid
* The unique chip identifier of the chip instance.
*
* @field chid_cpro
* The certificate production status of the chip instance.
*
* @field chid_csec
* The certificate security mode of the chip instance.
*
* @field chid_epro
* The effective production status of the chip instance.
*
* @field chid_esec
* The effective security mode of the chip instance.
*
* @field chid_iuou
* The internal use-only unit status of the chip instance.
*
* @field chid_rsch
* The research mode of the chip instance.
*
* @field chid_euou
* The engineering use-only unit status of the chip instance.
*
* Added in version 1 of the structure.
*
* @field chid_esdm
* The extended security domain of the chip instance.
*
* Added in version 3 of the structure.
*
* @field chid_fpgt
* The factory pre-release global trust status of the chip instance.
*
* Added in version 4 of the structure.
*
* @field chid_udid
* The universal device identifier of the chip instance.
*
* Added in version 5 of the structure.
*
* @const chid_fchp
* The cryptex chip identifier of the chip instance.
*
* Added in version 6 of the structure.
*
* @const chid_type
* The cryptex type identifier of the chip instance.
*
* Added in version 6 of the structure.
*
* @const chid_styp
* The cryptex subtype identifier of the chip instance.
*
* Added in version 6 of the structure.
*
* @field chid_clas
* The product class of the chip instance.
*
* Added in version 6 of the structure.
*/
IMG4_API_AVAILABLE_20200508
typedef struct _img4_chip_instance {
img4_struct_version_t chid_version;
const img4_chip_t *chid_chip_family;
img4_chip_instance_omit_t chid_omit;
uint32_t chid_cepo;
uint32_t chid_bord;
uint32_t chid_chip;
uint32_t chid_sdom;
uint64_t chid_ecid;
bool chid_cpro;
bool chid_csec;
bool chid_epro;
bool chid_esec;
bool chid_iuou;
bool chid_rsch;
bool chid_euou;
uint32_t chid_esdm;
bool chid_fpgt;
img4_dgst_t chid_udid;
uint32_t chid_fchp;
uint32_t chid_type;
uint32_t chid_styp;
uint32_t chid_clas;
} img4_chip_instance_t;
/*!
* @function IMG4_CHIP_INSTANCE_INIT
* A convenience initializer which can be used to initialize a chip instance to
* a given family.
*
* @param _family
* The family of chip.
*
* @result
* A fully-initialized structure of the appropriate version supported by the
* implementation. The resulting chip instance omits no identifiers.
*/
#define IMG4_CHIP_INSTANCE_INIT(_family) (img4_chip_instance_t){ \
.chid_version = IMG4_CHIP_INSTANCE_STRUCT_VERSION, \
.chid_chip_family = (_family), \
.chid_omit = 0, \
.chid_cepo = 0, \
.chid_bord = 0, \
.chid_chip = 0, \
.chid_sdom = 0, \
.chid_ecid = 0, \
.chid_cpro = false, \
.chid_csec = false, \
.chid_epro = false, \
.chid_esec = false, \
.chid_iuou = false, \
.chid_rsch = false, \
.chid_euou = false, \
.chid_esdm = 0, \
.chid_fpgt = false, \
.chid_udid = {0}, \
.chid_fchp = 0, \
.chid_type = 0, \
.chid_styp = 0, \
.chid_clas = 0, \
}
/*!
* @function img4_chip_init_from_buff
* Initializes a buffer as a chip object.
*
* @param buff
* A pointer to the storage to use for the chip object.
*
* @param len
* The size of the buffer.
*
* @discussion
* The caller is expected to pass a buffer that is "big enough". If the provided
* buffer is too small, the implementation will abort the caller.
*
* @example
*
* uint8_t _buff[IMG4_CHIP_SIZE_RECOMMENDED];
* img4_chip_t *chip = NULL;
*
* chip = img4_chip_init_from_buff(_buff, sizeof(_buff));
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
img4_chip_t *
img4_chip_init_from_buff(void *__sized_by(len) buff, size_t len);
#else
#define img4_chip_init_from_buff (img4if->i4if_v7.chip_init_from_buff)
#endif
/*!
* @function img4_chip_select_personalized_ap
* Returns the chip appropriate for personalized verification against the host
* AP.
*
* @result
* The personalized chip environment for the host which corresponds to its
* silicon identity.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT OS_WARN_RESULT
const img4_chip_t *
img4_chip_select_personalized_ap(void);
#else
#define img4_chip_select_personalized_ap(...) \
(img4if->i4if_v7.chip_select_personalized_ap(__VA_ARGS__))
#endif
/*!
* @function img4_chip_select_personalized_sep
* Returns the chip appropriate for personalized verification against the host
* SEP.
*
* @result
* The personalized chip environment for the host's SEP which corresponds to its
* silicon identity. This will return NULL when called outside of the SEP
* runtime.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211119
OS_EXPORT OS_WARN_RESULT
const img4_chip_t *_Nullable
img4_chip_select_personalized_sep(void);
#else
#define img4_chip_select_personalized_sep(...) \
(img4if->i4if_v16.chip_select_personalized_sep(__VA_ARGS__))
#endif
/*!
* @function img4_chip_select_categorized_ap
* Returns the chip appropriate for categorized verification against the host
* AP.
*
* @result
* The categorized chip environment for the host which corresponds to its
* silicon identity. If the host has no AP category defined for it, NULL will be
* returned.
*
* @discussion
* Categorized chip environments have been scuttled and were never used. Please
* remove all uses of this function.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210305
OS_EXPORT OS_WARN_RESULT
const img4_chip_t *_Nullable
img4_chip_select_categorized_ap(void);
#else
#define img4_chip_select_categorized_ap(...) \
(img4if->i4if_v12.chip_select_categorized_ap(__VA_ARGS__))
#endif
/*!
* @function img4_chip_select_effective_ap
* Returns the chip appropriate for verification against the host AP.
*
* @result
* The currently enforced chip environment for the host. This interface is
* generally only useful on the AP.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT OS_WARN_RESULT
const img4_chip_t *
img4_chip_select_effective_ap(void);
#else
#define img4_chip_select_effective_ap(...) \
(img4if->i4if_v7.chip_select_effective_ap(__VA_ARGS__))
#endif
/*!
* @function img4_chip_select_cryptex1_boot
* Returns the appropriate Cryptex1 boot chip environment for the currently-
* booted effective AP environment.
*
* @result
* The chip environment to use for verification.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211126
OS_EXPORT OS_WARN_RESULT
const img4_chip_t *
img4_chip_select_cryptex1_boot(void);
#else
#define img4_chip_select_cryptex1_boot(...) \
(img4if->i4if_v17.chip_select_cryptex1_boot(__VA_ARGS__))
#endif
/*!
* @function img4_chip_select_cryptex1_preboot
* Returns the appropriate Cryptex1 pre-reboot chip environment for the
* currently-booted effective AP environment.
*
* @result
* The chip environment to use for verification.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211126
OS_EXPORT OS_WARN_RESULT
const img4_chip_t *
img4_chip_select_cryptex1_preboot(void);
#else
#define img4_chip_select_cryptex1_preboot(...) \
(img4if->i4if_v17.chip_select_cryptex1_preboot(__VA_ARGS__))
#endif
/*!
* @function img4_chip_get_cryptex1_boot
* Returns the appropriate Cryptex1 boot chip environment associated with a
* given AP environment.
*
* @param chip
* The AP environment for which to obtain the associated Cryptex1 environment.
*
* @result
* The Cryptex1 chip environment associated with {@link chip}. If there is no
* Cryptex1 association, NULL is returned.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220401
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
const img4_chip_t *_Nullable
img4_chip_get_cryptex1_boot(const img4_chip_t *chip);
#else
#define img4_chip_get_cryptex1_boot(...) \
(img4if->i4if_v18.chip_get_cryptex1_boot(__VA_ARGS__))
#endif
/*!
* @function img4_chip_get_cryptex1_boot_proposal
* Returns the appropriate Cryptex1 boot proposal chip environment associated
* with a given AP environment.
*
* @param chip
* The AP environment for which to obtain the associated Cryptex1 proposal
* environment.
*
* @result
* The Cryptex1 proposal chip environment associated with {@link chip}. If
* there is no Cryptex1 association, NULL is returned.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220401
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
const img4_chip_t *_Nullable
img4_chip_get_cryptex1_boot_proposal(const img4_chip_t *chip);
#else
#define img4_chip_get_cryptex1_boot_proposal(...) \
(img4if->i4if_v18.chip_get_cryptex1_boot_proposal(__VA_ARGS__))
#endif
/*!
* @function img4_chip_instantiate
* Returns an instantiation of the given chip using the default runtime where
* necessary.
*
* @param chip
* The chip to instantiate.
*
* @param chip_instance
* Upon successful return, storage to be populated with the instantiated chip.
* Upon failure, the contents of this storage are undefined.
*
* @result
* Upon success, zero is returned. Otherwise, one of the following error codes
* will be returned:
*
* [EXDEV] There was an error querying the runtime's identity oracle
* [ENODATA] The expected property in the runtime's identity oracle was
* of an unexpected type
* [EOVERFLOW] The expected property in the runtime's identity oracle had
* a value that was too large to be represented in the
* expected type
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT OS_WARN_RESULT OS_NONNULL1 OS_NONNULL2
errno_t
img4_chip_instantiate(const img4_chip_t *chip,
img4_chip_instance_t *chip_instance);
#else
#define img4_chip_instantiate(...) \
(img4if->i4if_v7.chip_instantiate(__VA_ARGS__))
#endif
/*!
* @function img4_chip_custom
* Returns a custom chip derived from the given chip instance. The
* {@link chid_chip_family} field of the given instance will be used as a
* template from which to derive the new chip.
*
* @param chip_instance
* The instance of the custom chip.
*
* The memory referenced by this pointer must be static or otherwise guaranteed
* to be valid for the duration of the caller's use of the custom chip.
*
* @param chip
* A pointer to storage for the new custom chip.
*
* The memory referenced by this pointer must be static or otherwise guaranteed
* to be valid for the duration of the caller's use of the custom chip.
*
* This pointer should be obtained as the result of a call to
* {@link img4_chip_init_from_buff}.
*
* @result
* A new custom chip.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT OS_WARN_RESULT OS_NONNULL1
const img4_chip_t *
img4_chip_custom(const img4_chip_instance_t *chip_instance, img4_chip_t *chip);
#else
#define img4_chip_custom(...) (img4if->i4if_v7.chip_custom(__VA_ARGS__))
#endif
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMG4_CHIP_H

View file

@ -0,0 +1,214 @@
/*!
* @header
* AP chip environments.
*/
#ifndef __IMG4_CHIP_AP_H
#define __IMG4_CHIP_AP_H
#ifndef __IMG4_INDIRECT
#error "Please #include <img4/firmware.h> instead of this file directly"
#endif // __IMG4_INDIRECT
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @const IMG4_CHIP_AP_SHA1
* The Application Processor on an Apple ARM SoC with an embedded sha1
* certifcate chain.
*
* This chip environment represents one unique instance of such a chip.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT
const img4_chip_t _img4_chip_ap_sha1;
#define IMG4_CHIP_AP_SHA1 (&_img4_chip_ap_sha1)
#else
#define IMG4_CHIP_AP_SHA1 (img4if->i4if_v7.chip_ap_sha1)
#endif
/*!
* @const IMG4_CHIP_AP_SHA2_384
* The Application Processor on an Apple ARM SoC with an embedded sha2-384
* certifcate chain.
*
* This chip environment represents one unique instance of such a chip.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT
const img4_chip_t _img4_chip_ap_sha2_384;
#define IMG4_CHIP_AP_SHA2_384 (&_img4_chip_ap_sha2_384)
#else
#define IMG4_CHIP_AP_SHA2_384 (img4if->i4if_v7.chip_ap_sha2_384)
#endif
/*!
* @const IMG4_CHIP_AP_HYBRID
* An Intel x86 processor whose chain of trust is rooted in an instance of a
* {@link IMG4_CHIP_AP_SHA2_384} chip. Firmwares executed on this chip are
* authenticated against the characteristics of the corresponding AP chip
* environment and not the characteristics of the x86 processor.
*
* This chip environment represents one unique instance of such a chip pair.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT
const img4_chip_t _img4_chip_ap_hybrid;
#define IMG4_CHIP_AP_HYBRID (&_img4_chip_ap_hybrid)
#else
#define IMG4_CHIP_AP_HYBRID (img4if->i4if_v7.chip_ap_hybrid)
#endif
/*!
* @const IMG4_CHIP_AP_REDUCED
* An Application Processor on an Apple ARM SoC operating in a reduced security
* configuration.
*
* This chip cannot be uniquely identified.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT
const img4_chip_t _img4_chip_ap_reduced;
#define IMG4_CHIP_AP_REDUCED (&_img4_chip_ap_reduced)
#else
#define IMG4_CHIP_AP_REDUCED (img4if->i4if_v7.chip_ap_reduced)
#endif
/*!
* @const IMG4_CHIP_AP_PERMISSIVE
* An Application Processor on an Apple ARM SoC operating entirely within the
* user's authority.
*
* This chip's identity is rooted in a device-specific authority rather than one
* maintained by Apple.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT
const img4_chip_t _img4_chip_ap_permissive;
#define IMG4_CHIP_AP_PERMISSIVE (&_img4_chip_ap_permissive)
#else
#define IMG4_CHIP_AP_PERMISSIVE (img4if->i4if_v8.chip_ap_permissive)
#endif
/*!
* @const IMG4_CHIP_AP_LOCAL_BLESSED
* An Application Processor on an Apple ARM SoC which is executing payloads from
* a future local policy that has not yet booted.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220513
OS_EXPORT
const img4_chip_t _img4_chip_ap_local_blessed;
#define IMG4_CHIP_AP_LOCAL_BLESSED (&_img4_chip_ap_local_blessed)
#else
#define IMG4_CHIP_AP_LOCAL_BLESSED (img4if->i4if_v18.chip_ap_local_blessed)
#endif
/*!
* @const IMG4_CHIP_AP_HYBRID_MEDIUM
* An Intel x86 processor whose chain of trust is rooted in an instance of a
* {@link IMG4_CHIP_AP_SHA2_384} chip and is operating in a "medium security"
* mode due to a user-approved security degradation.
*
* This chip cannot be uniquely identified.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT
const img4_chip_t _img4_chip_ap_hybrid_medium;
#define IMG4_CHIP_AP_HYBRID_MEDIUM (&_img4_chip_ap_hybrid_medium)
#else
#define IMG4_CHIP_AP_HYBRID_MEDIUM (img4if->i4if_v8.chip_ap_hybrid_medium)
#endif
/*!
* @const IMG4_CHIP_AP_HYBRID_RELAXED
* An Intel x86 processor whose chain of trust is rooted in an instance of a
* {@link IMG4_CHIP_AP_SHA2_384} chip and is operating with no secure boot
* due to a user-approved security degradation.
*
* This chip cannot be uniquely identified.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT
const img4_chip_t _img4_chip_ap_hybrid_relaxed;
#define IMG4_CHIP_AP_HYBRID_RELAXED (&_img4_chip_ap_hybrid_relaxed)
#else
#define IMG4_CHIP_AP_HYBRID_RELAXED (img4if->i4if_v8.chip_ap_hybrid_relaxed)
#endif
/*!
* @const IMG4_CHIP_AP_INTRANSIGENT
* An Application Processor which is incapable of executing code. This chip
* environment's root of trust is a certificate authority which has never and
* will never issue any certificates.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210113
OS_EXPORT
const img4_chip_t _img4_chip_ap_intransigent;
#define IMG4_CHIP_AP_INTRANSIGENT (&_img4_chip_ap_intransigent)
#else
#define IMG4_CHIP_AP_INTRANSIGENT (img4if->i4if_v11.chip_ap_intransigent)
#endif
/*!
* @const IMG4_CHIP_AP_SUPPLEMENTAL
* An Application Processor whose root of trust resides in the
* {@link IMG4_RUNTIME_OBJECT_SPEC_SUPPLEMENTAL_ROOT} object. Once the
* supplemental root object is executed on the host's AP, this chip environment
* is available to execute payloads.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210113
OS_EXPORT
const img4_chip_t _img4_chip_ap_supplemental;
#define IMG4_CHIP_AP_SUPPLEMENTAL (&_img4_chip_ap_supplemental)
#else
#define IMG4_CHIP_AP_SUPPLEMENTAL (img4if->i4if_v11.chip_ap_supplemental)
#endif
/*!
* @const IMG4_CHIP_AP_VMA2
* The Application Processor of a virtualized Apple ARM device.
*
* This chip environment represents one unique instance of such a chip on the
* host device.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210113
OS_EXPORT
const img4_chip_t _img4_chip_ap_vma2;
#define IMG4_CHIP_AP_VMA2 (&_img4_chip_ap_vma2)
#else
#define IMG4_CHIP_AP_VMA2 (img4if->i4if_v13.chip_ap_vma2)
#endif
/*!
* @const IMG4_CHIP_AP_VMA2_CLONE
* The Application Processor of a virtualized Apple ARM device which has been
* cloned from another on the same host.
*
* This chip environment cannot be uniquely identified.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210113
OS_EXPORT
const img4_chip_t _img4_chip_ap_vma2_clone;
#define IMG4_CHIP_AP_VMA2_CLONE (&_img4_chip_ap_vma2_clone)
#else
#define IMG4_CHIP_AP_VMA2_CLONE (img4if->i4if_v13.chip_ap_vma2_clone)
#endif
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMG4_CHIP_AP_H

View file

@ -0,0 +1,120 @@
/*!
* @header
* Categorized AP chip environments. These are now defunct.
*/
#ifndef __IMG4_CHIP_AP_CATEGORY_H
#define __IMG4_CHIP_AP_CATEGORY_H
#ifndef __IMG4_INDIRECT
#error "Please #include <img4/firmware.h> instead of this file directly"
#endif // __IMG4_INDIRECT
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @const IMG4_CHIP_AP_CATEGORY_FF02
* The Application Processor on an Intel Mac product.
*
* This chip environment represents one unique instance of such a chip, though
* the uniqueness is not enforced by a secure boot chain with anti-replay
* properties, and therefore this chip environment should be considered as
* equivalent to a global signing environment.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210305
OS_EXPORT
const img4_chip_t _img4_chip_ap_category_ff02;
#define IMG4_CHIP_AP_CATEGORY_FF02 (&_img4_chip_ap_category_ff02)
#else
#define IMG4_CHIP_AP_CATEGORY_FF02 (img4if->i4if_v12.chip_ap_category_ff02)
#endif
/*!
* @const IMG4_CHIP_AP_CATEGORY_FF03
* An Intel x86 processor whose chain of trust is rooted in an instance of a
* {@link IMG4_CHIP_AP_SHA2_384} chip.
*
* This chip environment represents one unique instance of such a chip pair.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210305
OS_EXPORT
const img4_chip_t _img4_chip_ap_category_ff03;
#define IMG4_CHIP_AP_CATEGORY_FF03 (&_img4_chip_ap_category_ff03)
#else
#define IMG4_CHIP_AP_CATEGORY_FF03 (img4if->i4if_v12.chip_ap_category_ff03)
#endif
/*!
* @const IMG4_CHIP_AP_CATEGORY_FF04_F0
* The Application Processor of an Apple ARM SoC in an Apple Silicon Mac
* product.
*
* This chip environment represents one unique instance of such a chip.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210305
OS_EXPORT
const img4_chip_t _img4_chip_ap_category_ff04_f0;
#define IMG4_CHIP_AP_CATEGORY_FF04_F0 (&_img4_chip_ap_category_ff04_f0)
#else
#define IMG4_CHIP_AP_CATEGORY_FF04_F0 \
(img4if->i4if_v12.chip_ap_category_ff04_f0)
#endif
/*!
* @const IMG4_CHIP_AP_CATEGORY_FF04_F1
* The Application Processor of an Apple ARM SoC in an iPhone, iPad, or iPod
* touch product.
*
* This chip environment represents one unique instance of such a chip.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210305
OS_EXPORT
const img4_chip_t _img4_chip_ap_category_ff04_f1;
#define IMG4_CHIP_AP_CATEGORY_FF04_F1 (&_img4_chip_ap_category_ff04_f1)
#else
#define IMG4_CHIP_AP_CATEGORY_FF04_F1 \
(img4if->i4if_v12.chip_ap_category_ff04_f1)
#endif
/*!
* @const IMG4_CHIP_AP_CATEGORY_FF04_F2
* The Application Processor of an Apple ARM SoC in an watch product.
*
* This chip environment represents one unique instance of such a chip.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210305
OS_EXPORT
const img4_chip_t _img4_chip_ap_category_ff04_f2;
#define IMG4_CHIP_AP_CATEGORY_FF04_F2 (&_img4_chip_ap_category_ff04_f2)
#else
#define IMG4_CHIP_AP_CATEGORY_FF04_F2 \
(img4if->i4if_v12.chip_ap_category_ff04_f2)
#endif
/*!
* @const IMG4_CHIP_AP_CATEGORY_FF04_F3
* The Application Processor of an Apple ARM SoC in an tv or HomePod product.
*
* This chip environment represents one unique instance of such a chip.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210305
OS_EXPORT
const img4_chip_t _img4_chip_ap_category_ff04_f3;
#define IMG4_CHIP_AP_CATEGORY_FF04_F3 (&_img4_chip_ap_category_ff04_f3)
#else
#define IMG4_CHIP_AP_CATEGORY_FF04_F3 \
(img4if->i4if_v12.chip_ap_category_ff04_f3)
#endif
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMG4_CHIP_AP_CATEGORY_H

View file

@ -0,0 +1,72 @@
/*!
* @header
* Software AP chip environments.
*/
#ifndef __IMG4_CHIP_AP_SOFTWARE_H
#define __IMG4_CHIP_AP_SOFTWARE_H
#ifndef __IMG4_INDIRECT
#error "Please #include <img4/firmware.h> instead of this file directly"
#endif // __IMG4_INDIRECT
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @const IMG4_CHIP_AP_SOFTWARE_FF00
* A software-defined chip environment whose firmwares are executed on any
* Application Processor on an Apple ARM SoC. The firmwares are loadable trust
* caches shipped with OTA update brains.
*
* This chip cannot be uniquely identified.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT
const img4_chip_t _img4_chip_ap_software_ff00;
#define IMG4_CHIP_AP_SOFTWARE_FF00 (&_img4_chip_ap_software_ff00)
#else
#define IMG4_CHIP_AP_SOFTWARE_FF00 (img4if->i4if_v7.chip_ap_software_ff00)
#endif
/*!
* @const IMG4_CHIP_AP_SOFTWARE_FF01
* A software-defined chip environment whose firmwares are executed on any
* Application Processor on an Apple ARM SoC. The firmwares are loadable trust
* caches which are shipped in the Install Assistant and loaded by an
* unprivileged trampoline.
*
* This chip cannot be uniquely identified.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT
const img4_chip_t _img4_chip_ap_software_ff01;
#define IMG4_CHIP_AP_SOFTWARE_FF01 (&_img4_chip_ap_software_ff01)
#else
#define IMG4_CHIP_AP_SOFTWARE_FF01 (img4if->i4if_v7.chip_ap_software_ff01)
#endif
/*!
* @const IMG4_CHIP_AP_SOFTWARE_FF06
* A software-defined chip environment whose firmwares are executed on any
* Application Processor on an Apple ARM SoC. The firmwares are loadable trust
* caches which are shipped in the preboot volume.
*
* This chip cannot be uniquely identified.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20210113
OS_EXPORT
const img4_chip_t _img4_chip_ap_software_ff06;
#define IMG4_CHIP_AP_SOFTWARE_FF06 (&_img4_chip_ap_software_ff06)
#else
#define IMG4_CHIP_AP_SOFTWARE_FF06 (img4if->i4if_v11.chip_ap_software_ff06)
#endif
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMG4_CHIP_AP_SOFTWARE_H

View file

@ -0,0 +1,422 @@
/*!
* @header
* Cryptex1 chip environments.
*/
#ifndef __IMG4_CHIP_CRYPTEX1_H
#define __IMG4_CHIP_CRYPTEX1_H
#ifndef __IMG4_INDIRECT
#error "Please #include <img4/firmware.h> instead of this file directly"
#endif // __IMG4_INDIRECT
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @const IMG4_CHIP_CRYPTEX1_BOOT
* A virtual coprocessor environment hosted on the AP which derives its unique
* identity from the hosting AP. This chip assists in booting the AP's
* userspace.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211126
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_boot;
#define IMG4_CHIP_CRYPTEX1_BOOT (&_img4_chip_cryptex1_boot)
#else
#define IMG4_CHIP_CRYPTEX1_BOOT (img4if->i4if_v17.chip_cryptex1_boot)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_BOOT_REDUCED
* A virtual coprocessor environment hosted on the reduced-security AP which
* derives its unique identity from the hosting AP. This chip assists in booting
* the AP's userspace.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211126
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_boot_reduced;
#define IMG4_CHIP_CRYPTEX1_BOOT_REDUCED \
(&_img4_chip_cryptex1_boot_reduced)
#else
#define IMG4_CHIP_CRYPTEX1_BOOT_REDUCED \
(img4if->i4if_v17.chip_cryptex1_boot_reduced)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_BOOT_PROPOSAL
* Equivalent to {@link IMG4_CHIP_CRYPTEX1_BOOT} with internal use constraints
* relaxed to permit verification in scenarios where the currently-booted AP may
* not represent the ultimate execution environment.
*
* @discussion
* This environment should not be used for payload execution on the AP and is
* intended to facilitate local policy signing in the SEP.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220401
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_boot_proposal;
#define IMG4_CHIP_CRYPTEX1_BOOT_PROPOSAL (&_img4_chip_cryptex1_boot_proposal)
#else
#define IMG4_CHIP_CRYPTEX1_BOOT_PROPOSAL \
(img4if->i4if_v18.chip_cryptex1_boot_proposal)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_BOOT_REDUCED_PROPOSAL
* Equivalent to {@link IMG4_CHIP_CRYPTEX1_BOOT_REDUCED} with internal use
* constraints relaxed to permit verification in scenarios where the currently-
* booted AP may not represent the ultimate execution environment.
*
* @discussion
* This environment should not be used for payload execution on the AP and is
* intended to facilitate local policy signing in the SEP.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220401
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_boot_reduced_proposal;
#define IMG4_CHIP_CRYPTEX1_BOOT_REDUCED_PROPOSAL \
(&_img4_chip_cryptex1_boot_reduced_proposal)
#else
#define IMG4_CHIP_CRYPTEX1_BOOT_REDUCED_PROPOSAL \
(img4if->i4if_v18.chip_cryptex1_boot_reduced_proposal)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_BOOT_X86
* A virtual coprocessor environment hosted on an x86 chip which has no unique
* identity. This chip assists in booting the x86 processor's userspace.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211126
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_boot_x86;
#define IMG4_CHIP_CRYPTEX1_BOOT_X86 (&_img4_chip_cryptex1_boot_x86)
#else
#define IMG4_CHIP_CRYPTEX1_BOOT_X86 (img4if->i4if_v17.chip_cryptex1_boot_x86)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_BOOT_STATIC_X86
* A virtual coprocessor environment hosted on an x86 chip which has no unique
* identity. This chip assists in booting the x86 processor's userspace. This
* chip has no ability to enforce expiration on its manifests.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220912
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_boot_static_x86;
#define IMG4_CHIP_CRYPTEX1_BOOT_STATIC_X86 \
(&_img4_chip_cryptex1_boot_static_x86)
#else
#define IMG4_CHIP_CRYPTEX1_BOOT_STATIC_X86 \
(img4if->i4if_v19.chip_cryptex1_boot_static_x86)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_BOOT_RELAXED_X86
* A virtual coprocessor environment hosted on an x86 chip which has no unique
* identity and has secure boot disabled. This chip assists in booting the x86
* processor's userspace.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220711
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_boot_relaxed_x86;
#define IMG4_CHIP_CRYPTEX1_BOOT_RELAXED_X86 \
(&_img4_chip_cryptex1_boot_relaxed_x86)
#else
#define IMG4_CHIP_CRYPTEX1_BOOT_RELAXED_X86 \
(img4if->i4if_v19.chip_cryptex1_boot_relaxed_x86)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_BOOT_VMA2
* A virtual coprocessor environment hosted on a virtualized ARM AP which
* derives its unique identity from the hosting AP. This chip assists in booting
* the AP's userspace.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220128
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_boot_vma2;
#define IMG4_CHIP_CRYPTEX1_BOOT_VMA2 (&_img4_chip_cryptex1_boot_vma2)
#else
#define IMG4_CHIP_CRYPTEX1_BOOT_VMA2 (img4if->i4if_v17.chip_cryptex1_boot_vma2)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_BOOT_VMA2_CLONE
* A virtual coprocessor environment hosted on a virtualized ARM AP which
* derives its unique identity from the hosting AP. This chip assists in booting
* the AP's userspace. This is the clone version which doesn't enforce ECID
* and UDID.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220322
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_boot_vma2_clone;
#define IMG4_CHIP_CRYPTEX1_BOOT_VMA2_CLONE \
(&_img4_chip_cryptex1_boot_vma2_clone)
#else
#define IMG4_CHIP_CRYPTEX1_BOOT_VMA2_CLONE \
(img4if->i4if_v18.chip_cryptex1_boot_vma2_clone)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_BOOT_VMA2_PROPOSAL
* Equivalent to {@link IMG4_CHIP_CRYPTEX1_BOOT_VMA2} with internal use
* constraints relaxed to permit verification in scenarios where the currently-
* booted AP may not represent the ultimate execution environment.
*
* @discussion
* This environment should not be used for payload execution on the AP and is
* intended to facilitate local policy signing in the BootPolicy kext.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220401
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_boot_vma2_proposal;
#define IMG4_CHIP_CRYPTEX1_BOOT_VMA2_PROPOSAL \
(&_img4_chip_cryptex1_boot_vma2_proposal)
#else
#define IMG4_CHIP_CRYPTEX1_BOOT_VMA2_PROPOSAL \
(img4if->i4if_v18.chip_cryptex1_boot_vma2_proposal)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_BOOT_VMA2_CLONE_PROPOSAL
* Equivalent to {@link IMG4_CHIP_CRYPTEX1_BOOT_VMA2_CLONE} with internal use
* constraints relaxed to permit verification in scenarios where the currently-
* booted AP may not represent the ultimate execution environment.
*
* @discussion
* This environment should not be used for payload execution on the AP and is
* intended to facilitate local policy signing in the BootPolicy kext.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220401
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_boot_vma2_clone_proposal;
#define IMG4_CHIP_CRYPTEX1_BOOT_VMA2_CLONE_PROPOSAL \
(&_img4_chip_cryptex1_boot_vma2_clone_proposal)
#else
#define IMG4_CHIP_CRYPTEX1_BOOT_VMA2_CLONE_PROPOSAL \
(img4if->i4if_v18.chip_cryptex1_boot_vma2_clone_proposal)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_PREBOOT
* A virtual coprocessor environment hosted on the AP which derives its unique
* identity from the hosting AP. This chip permits executing payloads intended
* for the next boot prior to that boot. It does not assist in booting the AP.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211126
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_preboot;
#define IMG4_CHIP_CRYPTEX1_PREBOOT (&_img4_chip_cryptex1_preboot)
#else
#define IMG4_CHIP_CRYPTEX1_PREBOOT (img4if->i4if_v17.chip_cryptex1_preboot)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_PREBOOT_REDUCED
* A virtual coprocessor environment hosted on the reduced-security AP which
* derives its unique identity from the hosting AP. This chip permits executing
* payloads intended for the next boot prior to that boot. It does not assist in
* booting the AP.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211126
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_preboot_reduced;
#define IMG4_CHIP_CRYPTEX1_PREBOOT_REDUCED \
(&_img4_chip_cryptex1_preboot_reduced)
#else
#define IMG4_CHIP_CRYPTEX1_PREBOOT_REDUCED \
(img4if->i4if_v17.chip_cryptex1_preboot_reduced)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_PREBOOT_X86
* A virtual coprocessor environment hosted on an x86 chip which has no unique
* identity. This chip permits executing payloads intended for the next boot
* prior to that boot. It does not assist in booting the x86 chip.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211126
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_preboot_x86;
#define IMG4_CHIP_CRYPTEX1_PREBOOT_X86 \
(&_img4_chip_cryptex1_preboot_x86)
#else
#define IMG4_CHIP_CRYPTEX1_PREBOOT_X86 \
(img4if->i4if_v17.chip_cryptex1_preboot_x86)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_PREBOOT_STATIC_X86
* A virtual coprocessor environment hosted on an x86 chip which has no unique
* identity. This chip permits executing payloads intended for the next boot
* prior to that boot. It does not assist in booting the x86 chip. This chip has
* no ability to enforce expiration on its manifests.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211126
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_preboot_static_x86;
#define IMG4_CHIP_CRYPTEX1_PREBOOT_STATIC_X86 \
(&_img4_chip_cryptex1_preboot_static_x86)
#else
#define IMG4_CHIP_CRYPTEX1_PREBOOT_STATIC_X86 \
(img4if->i4if_v19.chip_cryptex1_preboot_static_x86)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_PREBOOT_RELAXED_X86
* A virtual coprocessor environment hosted on an x86 chip which has no unique
* identity and has secure boot disabled. This chip permits executing payloads
* intended for the next boot prior to that boot. It does not assist in booting
* the x86 chip.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220711
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_preboot_relaxed_x86;
#define IMG4_CHIP_CRYPTEX1_PREBOOT_RELAXED_X86 \
(&_img4_chip_cryptex1_preboot_relaxed_x86)
#else
#define IMG4_CHIP_CRYPTEX1_PREBOOT_RELAXED_X86 \
(img4if->i4if_v17.chip_cryptex1_preboot_relaxed_x86)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_PREBOOT_VMA2
* A virtual coprocessor environment hosted on a virtualized ARM AP which
* derives its unique identity from the hosting AP. This chip permits executing
* payloads intended for the next boot prior to that boot. It does not assist in
* booting the AP.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220128
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_preboot_vma2;
#define IMG4_CHIP_CRYPTEX1_PREBOOT_VMA2 \
(&_img4_chip_cryptex1_preboot_vma2)
#else
#define IMG4_CHIP_CRYPTEX1_PREBOOT_VMA2 \
(img4if->i4if_v17.chip_cryptex1_preboot_vma2)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_PREBOOT_VMA2_CLONE
* A virtual coprocessor environment hosted on a virtualized ARM AP which
* derives its unique identity from the hosting AP. This chip permits executing
* payloads intended for the next boot prior to that boot. It does not assist in
* booting the AP. This is the clone version which doesn't enforce ECID
* and UDID.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220322
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_preboot_vma2_clone;
#define IMG4_CHIP_CRYPTEX1_PREBOOT_VMA2_CLONE \
(&_img4_chip_cryptex1_preboot_vma2_clone)
#else
#define IMG4_CHIP_CRYPTEX1_PREBOOT_VMA2_CLONE \
(img4if->i4if_v18.chip_cryptex1_preboot_vma2_clone)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_ASSET
* A virtual coprocessor environment hosted on the AP which derives its unique
* identity from the hosting AP. This chip assists in executing MobileAsset
* brain payloads during runtime, after the host AP has booted its userspace.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211126
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_asset;
#define IMG4_CHIP_CRYPTEX1_ASSET (&_img4_chip_cryptex1_asset)
#else
#define IMG4_CHIP_CRYPTEX1_ASSET (img4if->i4if_v17.chip_cryptex1_asset)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_ASSET_X86
* A virtual coprocessor environment hosted on the AP which derives its unique
* identity from the hosting AP. This chip assists in executing MobileAsset
* brain payloads during runtime, after the host AP has booted its userspace.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20220401
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_asset_x86;
#define IMG4_CHIP_CRYPTEX1_ASSET_X86 (&_img4_chip_cryptex1_asset_x86)
#else
#define IMG4_CHIP_CRYPTEX1_ASSET_X86 (img4if->i4if_v18.chip_cryptex1_asset_x86)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_GENERIC
* A virtual coprocessor environment hosted on the AP which derives its unique
* identity from the hosting AP. This chip assists in executing generic cryptex
* payloads during runtime, after the host AP has booted its userspace.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20221202
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_generic;
#define IMG4_CHIP_CRYPTEX1_GENERIC \
(&_img4_chip_cryptex1_generic)
#else
#define IMG4_CHIP_CRYPTEX1_GENERIC \
(img4if->i4if_v20.chip_cryptex1_generic)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_GENERIC_SUPPLEMENTAL
* A virtual coprocessor environment hosted on the AP which derives its unique
* identity from the hosting AP. This chip assists in executing generic cryptex
* payloads during runtime, after the host AP has booted its userspace. Its
* trust is rooted in a supplemental root of trust authorized by the Secure Boot
* CA.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20221202
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_generic_supplemental;
#define IMG4_CHIP_CRYPTEX1_GENERIC_SUPPLEMENTAL \
(&_img4_chip_cryptex1_generic_supplemental)
#else
#define IMG4_CHIP_CRYPTEX1_GENERIC_SUPPLEMENTAL \
(img4if->i4if_v20.chip_cryptex1_generic_supplemental)
#endif
/*!
* @const IMG4_CHIP_CRYPTEX1_GENERIC_X86
* A virtual coprocessor environment hosted on an x86 chip. This chip assists in
* executing generic cryptex payloads during runtime after the x86 chip has
* booted.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20221202
OS_EXPORT
const img4_chip_t _img4_chip_cryptex1_generic_x86;
#define IMG4_CHIP_CRYPTEX1_GENERIC_X86 \
(&_img4_chip_cryptex1_generic_x86)
#else
#define IMG4_CHIP_CRYPTEX1_GENERIC_X86 \
(img4if->i4if_v20.chip_cryptex1_generic_x86)
#endif
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMG4_CHIP_CRYPTEX1_H

View file

@ -0,0 +1,52 @@
/*!
* @header
* Cryptex1 chip environments.
*/
#ifndef __IMG4_CHIP_SEP_H
#define __IMG4_CHIP_SEP_H
#ifndef __IMG4_INDIRECT
#error "Please #include <img4/firmware.h> instead of this file directly"
#endif // __IMG4_INDIRECT
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @const IMG4_CHIP_SEP_SHA1
* The Secure Enclave Processor on an Apple ARM SoC with an embedded sha1
* certifcate chain.
*
* This chip environment represents one unique instance of such a chip.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211119
OS_EXPORT
const img4_chip_t _img4_chip_sep_sha1;
#define IMG4_CHIP_SEP_SHA1 (&_img4_chip_sep_sha1)
#else
#define IMG4_CHIP_SEP_SHA1 (img4if->i4if_v16.chip_sep_sha1)
#endif
/*!
* @const IMG4_CHIP_SEP_SHA2_384
* The Secure Enclave Processor on an Apple ARM SoC with an embedded sha2-384
* certifcate chain.
*
* This chip environment represents one unique instance of such a chip.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20211119
OS_EXPORT
const img4_chip_t _img4_chip_sep_sha2_384;
#define IMG4_CHIP_SEP_SHA2_384 (&_img4_chip_sep_sha2_384)
#else
#define IMG4_CHIP_SEP_SHA2_384 (img4if->i4if_v16.chip_sep_sha2_384)
#endif
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMG4_CHIP_SEP_H

View file

@ -0,0 +1,57 @@
/*!
* @header
* x86 chip environments.
*/
#ifndef __IMG4_CHIP_X86_H
#define __IMG4_CHIP_X86_H
#ifndef __IMG4_INDIRECT
#error "Please #include <img4/firmware.h> instead of this file directly"
#endif // __IMG4_INDIRECT
__BEGIN_DECLS
OS_ASSUME_NONNULL_BEGIN
OS_ASSUME_PTR_ABI_SINGLE_BEGIN
/*!
* @const IMG4_CHIP_X86
* An Intel x86 processor which cannot be uniquely identified.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT
const img4_chip_t _img4_chip_x86;
#define IMG4_CHIP_X86 (&_img4_chip_x86)
#else
#define IMG4_CHIP_X86 (img4if->i4if_v7.chip_x86)
#endif
/*!
* @const IMG4_CHIP_X86_SOFTWARE_8012
* A software-defined chip environment describing a virtualized x86 processor.
* Since the virtual machine is at the mercy of the VM, support for any sort of
* chip identity may not be available. Therefore this environment is returned
* from {@link img4_chip_select_personalized_ap} and
* {@link img4_chip_select_effective_ap} when it is called on a virtual machine
* so that the appropriate chip environment is present entirely in software.
*
* This environment provides an equivalent software identity to that of
* the {@link IMG4_CHIP_X86} chip environment on non-Gibraltar Macs.
*
* @discussion
* Do not use this environment directly.
*/
#if !XNU_KERNEL_PRIVATE
IMG4_API_AVAILABLE_20200508
OS_EXPORT
const img4_chip_t _img4_chip_x86_software_8012;
#define IMG4_CHIP_X86_SOFTWARE_8012 (&_img4_chip_x86_software_8012)
#else
#define IMG4_CHIP_X86_SOFTWARE_8012 (img4if->i4if_v7.chip_x86_software_8012)
#endif
OS_ASSUME_PTR_ABI_SINGLE_END
OS_ASSUME_NONNULL_END
__END_DECLS
#endif // __IMG4_CHIP_X86_H

Some files were not shown because too many files have changed in this diff Show more