xref: /xnu-11215.1.10/osfmk/kern/memset_s.c (revision 8d741a5de7ff4191bf97d57b9f54c2f6d4a15585)
1 /*
2  * Copyright (c) 2016 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <string.h>
30 #include <sys/errno.h>
31 #include <stdint.h>
32 
33 extern void   *secure_memset(void *, int, size_t);
34 
35 /*
36  * The memset_s function copies the value c into the first n bytes
37  * pointed by s. No more than smax bytes will be copied.
38  *
39  * In contrast to the memset function, calls to memset_s will never
40  * be ''optimised away'' by a compiler, ensuring the memory copy
41  * even if s is not accessed anymore after this call.
42  */
43 int
memset_s(void * s,size_t smax,int c,size_t n)44 memset_s(void *s, size_t smax, int c, size_t n)
45 {
46 	int err = 0;
47 
48 	if (s == NULL) {
49 		return EINVAL;
50 	}
51 	if (smax > RSIZE_MAX) {
52 		return E2BIG;
53 	}
54 	if (n > smax) {
55 		n = smax;
56 		err = EOVERFLOW;
57 	}
58 
59 	/*
60 	 * secure_memset is defined in assembly, we therefore
61 	 * expect that the compiler will not inline the call.
62 	 */
63 	secure_memset(s, c, n);
64 
65 	return err;
66 }
67 
68 int
timingsafe_bcmp(const void * b1,const void * b2,size_t n)69 timingsafe_bcmp(const void *b1, const void *b2, size_t n)
70 {
71 	const unsigned char *p1 = b1, *p2 = b2;
72 	unsigned char ret = 0;
73 
74 	for (; n > 0; n--) {
75 		ret |= *p1++ ^ *p2++;
76 	}
77 
78 	/* map zero to zero and nonzero to one */
79 	return (ret + 0xff) >> 8;
80 }
81