]> git.saurik.com Git - apple/security.git/blob - keychain/SecureObjectSync/SOSGenCount.c
Security-59306.11.20.tar.gz
[apple/security.git] / keychain / SecureObjectSync / SOSGenCount.c
1 //
2 // SOSGenCount.c
3 // sec
4 //
5 // Created by Richard Murphy on 1/29/15.
6 //
7 //
8
9 #include "SOSGenCount.h"
10 #include <utilities/SecCFWrappers.h>
11 #include <CoreFoundation/CFLocale.h>
12 #include <utilities/der_plist.h>
13 #include <utilities/der_plist_internal.h>
14
15
16 static CFAbsoluteTime SOSGenerationCountGetDateBits(int64_t genValue) {
17 return (uint32_t) ((((uint64_t) genValue) >> 32) << 1);
18 }
19
20 void SOSGenerationCountWithDescription(SOSGenCountRef gen, void (^operation)(CFStringRef description)) {
21 CFStringRef description = SOSGenerationCountCopyDescription(gen);
22
23 operation(description);
24
25 CFReleaseSafe(description);
26 }
27
28 CFStringRef SOSGenerationCountCopyDescription(SOSGenCountRef gen) {
29 int64_t value = SOSGetGenerationSint(gen);
30
31 CFMutableStringRef gcDecsription = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFSTR("["));
32
33 withStringOfAbsoluteTime(SOSGenerationCountGetDateBits(value), ^(CFStringRef decription) {
34 CFStringAppend(gcDecsription, decription);
35 });
36
37 CFStringAppendFormat(gcDecsription, NULL, CFSTR(" %u]"), (uint32_t)(value & 0xFFFFFFFF));
38
39 return gcDecsription;
40 }
41
42 int64_t SOSGetGenerationSint(SOSGenCountRef gen) {
43 int64_t value;
44 if(!gen) return 0;
45 CFNumberGetValue(gen, kCFNumberSInt64Type, &value);
46 return value;
47 }
48
49 static int64_t sosGenerationSetHighBits(int64_t value, int32_t high_31)
50 {
51 value &= 0xFFFFFFFF; // Keep the low 32 bits.
52 value |= ((int64_t) high_31) << 32;
53
54 return value;
55 }
56
57 static SOSGenCountRef sosGenerationCreateOrIncrement(SOSGenCountRef gen) {
58 int64_t value = 0;
59
60 if(gen) {
61 value = SOSGetGenerationSint(gen);
62 }
63
64 if((value >> 32) == 0) {
65 uint32_t seconds = CFAbsoluteTimeGetCurrent(); // seconds
66 value = sosGenerationSetHighBits(value, (seconds >> 1));
67 }
68
69 value++;
70 return CFNumberCreate(NULL, kCFNumberSInt64Type, &value);
71 }
72
73 SOSGenCountRef SOSGenerationCreate() {
74 return sosGenerationCreateOrIncrement(NULL);
75 }
76
77
78 // We need this for a circle gencount test
79 SOSGenCountRef SOSGenerationCreateWithValue(int64_t value) {
80 return CFNumberCreate(NULL, kCFNumberSInt64Type, &value);
81 }
82
83 SOSGenCountRef SOSGenerationIncrementAndCreate(SOSGenCountRef gen) {
84 return sosGenerationCreateOrIncrement(gen);
85 }
86
87 SOSGenCountRef SOSGenerationCopy(SOSGenCountRef gen) {
88 if(!gen) return NULL;
89 int64_t value = SOSGetGenerationSint(gen);
90 return CFNumberCreate(NULL, kCFNumberSInt64Type, &value);
91 }
92
93 // Is current older than proposed?
94 bool SOSGenerationIsOlder(SOSGenCountRef older, SOSGenCountRef newer) {
95 switch(CFNumberCompare(older, newer, NULL)) {
96 case kCFCompareLessThan: return true;
97 case kCFCompareEqualTo: return false;
98 case kCFCompareGreaterThan: return false;
99 }
100 return false;
101 }
102
103 // Is current older than proposed?
104 static bool SOSGenerationIsOlderOrEqual(SOSGenCountRef older, SOSGenCountRef newer) {
105 switch(CFNumberCompare(older, newer, NULL)) {
106 case kCFCompareLessThan: return true;
107 case kCFCompareEqualTo: return true;
108 case kCFCompareGreaterThan: return false;
109 }
110 return false;
111 }
112
113
114 SOSGenCountRef SOSGenerationCreateWithBaseline(SOSGenCountRef reference) {
115 SOSGenCountRef retval = SOSGenerationCreate();
116 if(SOSGenerationIsOlderOrEqual(retval, reference)) {
117 CFReleaseNull(retval);
118 retval = SOSGenerationIncrementAndCreate(reference);
119 }
120 return retval;
121 }
122
123
124 SOSGenCountRef SOSGenCountCreateFromDER(CFAllocatorRef allocator, CFErrorRef* error,
125 const uint8_t** der_p, const uint8_t *der_end) {
126 SOSGenCountRef retval = NULL;
127 *der_p = der_decode_number(allocator, 0, &retval, error, *der_p, der_end);
128 if(retval == NULL)
129 retval = SOSGenerationCreate();
130 return retval;
131 }
132
133 size_t SOSGenCountGetDEREncodedSize(SOSGenCountRef gencount, CFErrorRef *error) {
134 return der_sizeof_number(gencount, error);
135 }
136
137 uint8_t *SOSGenCountEncodeToDER(SOSGenCountRef gencount, CFErrorRef* error, const uint8_t* der, uint8_t* der_end) {
138 return der_encode_number(gencount, error, der, der_end);
139 }
140
141
142