]> git.saurik.com Git - apple/security.git/blob - OSX/utilities/der_number.c
Security-59754.41.1.tar.gz
[apple/security.git] / OSX / utilities / der_number.c
1 /*
2 * Copyright (c) 2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25
26 #include <stdio.h>
27
28 #include "utilities/SecCFRelease.h"
29 #include "utilities/der_plist.h"
30 #include "utilities/der_plist_internal.h"
31
32 #include <corecrypto/ccder.h>
33 #include <CoreFoundation/CoreFoundation.h>
34
35
36 const uint8_t* der_decode_number(CFAllocatorRef allocator,
37 CFNumberRef* number, CFErrorRef *error,
38 const uint8_t* der, const uint8_t *der_end)
39 {
40 if (NULL == der) {
41 SecCFDERCreateError(kSecDERErrorNullInput, CFSTR("null input"), NULL, error);
42 return NULL;
43 }
44
45 size_t payload_size = 0;
46 const uint8_t *payload = ccder_decode_tl(CCDER_INTEGER, &payload_size, der, der_end);
47
48 if (NULL == payload || (ssize_t) (der_end - payload) < (ssize_t) payload_size) {
49 SecCFDERCreateError(kSecDERErrorUnknownEncoding, CFSTR("Unknown number encoding"), NULL, error);
50 return NULL;
51 }
52 if (payload_size > sizeof(long long)) {
53 SecCFDERCreateError(kSecDERErrorUnsupportedNumberType, CFSTR("Number too large"), NULL, error);
54 return NULL;
55 }
56
57 long long value = 0;
58
59 if (payload_size > 0) {
60 if ((*payload & 0x80) == 0x80)
61 value = -1; // Negative integers fill with 1s so we end up negative.
62
63 const uint8_t* const payload_end = payload + payload_size;
64
65 for (const uint8_t *payload_byte = payload;
66 payload_byte < payload_end;
67 ++payload_byte) {
68 value <<= 8;
69 value |= *payload_byte;
70 }
71 }
72
73 *number = CFNumberCreate(allocator, kCFNumberLongLongType, &value);
74
75 if (*number == NULL) {
76 SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Number allocation failed"), NULL, error);
77 return NULL;
78 }
79
80 return payload + payload_size;
81 }
82
83
84 static inline uint8_t byte_of(size_t byteNumber, long long value)
85 {
86 return value >> (8 * (byteNumber - 1));
87 }
88
89 static inline size_t bytes_when_encoded(long long value)
90 {
91 size_t bytes_encoded = sizeof(long long);
92
93 uint8_t first_byte = byte_of(bytes_encoded, value);
94
95 // Skip initial 0xFFs or 0x00
96 if (first_byte == 0xFF || first_byte == 0x00) {
97 do {
98 --bytes_encoded;
99 } while (bytes_encoded > 1 && (byte_of(bytes_encoded, value) == first_byte));
100
101 if ((first_byte & 0x80) != (byte_of(bytes_encoded, value) & 0x80))
102 bytes_encoded += 1;
103 }
104
105 return bytes_encoded;
106 }
107
108 size_t der_sizeof_number(CFNumberRef data, CFErrorRef *error)
109 {
110 long long value;
111 if (!CFNumberGetValue(data, kCFNumberLongLongType, &value)) {
112 SecCFDERCreateError(kSecDERErrorUnsupportedNumberType, CFSTR("Unable to get number from data"), NULL, error);
113 return 0;
114 }
115
116 return ccder_sizeof(CCDER_INTEGER, bytes_when_encoded(value));
117 }
118
119 uint8_t* der_encode_number(CFNumberRef number, CFErrorRef *error,
120 const uint8_t *der, uint8_t *der_end)
121 {
122 long long value;
123 if (!CFNumberGetValue(number, kCFNumberLongLongType, &value)) {
124 SecCFDERCreateError(kSecDERErrorUnsupportedNumberType, CFSTR("Unable to get number from data"), NULL, error);
125 return NULL;
126 }
127
128 size_t first_byte_to_include = bytes_when_encoded(value);
129
130 if (!der_end || (ssize_t) (der_end - der) < (ssize_t) first_byte_to_include) {
131 SecCFDERCreateError(kSecDERErrorAllocationFailure, CFSTR("Unknown size"), NULL, error);
132 return NULL;
133 }
134
135 // Put the bytes we should include on the end.
136 for(size_t bytes_included = 0; bytes_included < first_byte_to_include; ++bytes_included)
137 {
138 --der_end;
139 *der_end = value & 0xFF;
140 value >>= 8;
141 }
142
143 return SecCCDEREncodeHandleResult(ccder_encode_tl(CCDER_INTEGER, first_byte_to_include, der, der_end),
144 error);
145
146 }