/ OSX / utilities / SecPaddingConfigurations.c
SecPaddingConfigurations.c
 1  /*
 2   * Copyright (c) 2017 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  #define SecPaddingDomain CFSTR("com.apple.security.padding")
25  
26  typedef enum {
27  	SecPaddingErrorUnknownType     = -1
28  } SecPaddingError;
29  
30  #include "debugging.h"
31  #include "SecCFError.h"
32  #include "SecCFWrappers.h"
33  #include <Security/SecPaddingConfigurationsPriv.h>
34  
35  #pragma mark Padding Helper Methods
36  
37  // Compute the next power of two
38  // Requires: v <= UINT64_MAX/2
39  static uint64_t nextPowerOfTwo(uint64_t v)
40  {
41  	if (v > (UINT64_MAX>>1)) {
42  		secerror("Overflowing uint64_t by requesting nextPowerOfTwo of: %llx", v);
43  		assert(0);
44  	}
45  	if (v & (v - 1)) {
46  		// Not already a power of 2
47  		return ((uint64_t)1 << ((int)sizeof(v)*8 - __builtin_clzll(v)));
48  	} else {
49  		// Already a power of 2
50  		return v;
51  	}
52  }
53  
54  // Round to a multiple of n
55  // Requires: v+n <= UINT64_MAX
56  static uint64_t nextMultiple(uint64_t v,uint64_t n)
57  {
58  	// Multiples of 0 are 0. Preventing division by 0.
59  	if (n == 0) {
60  		return 0;
61  	}
62  
63  	if (n <= 0 || v > (UINT64_MAX-n)) {
64  		secerror("Overflowing uint64_t by requesting nextMutiple with parameters v: %llx and n: %llx", v, n);
65  		assert(0);
66  	}
67  	return n*((v+n-1)/n);
68  }
69  
70  #pragma mark Padding Configurations
71  
72  int64_t SecPaddingCompute(SecPaddingType type, uint32_t size, CFErrorRef *error) {
73  	if (type != SecPaddingTypeMMCS) {
74  		if (error) {
75  			*error = CFErrorCreate(CFAllocatorGetDefault(), SecPaddingDomain, SecPaddingErrorUnknownType, NULL);
76  		}
77  		return SecPaddingErrorUnknownType;
78  	}
79  
80  	int64_t paddedSize = 0;
81  
82  	if (size <= 64){
83  		paddedSize = 64;
84  	} else if (size <= 1024) {
85  		paddedSize = nextPowerOfTwo(size);
86  	} else if (size <= 32000) {
87  		paddedSize = nextMultiple(size, 1024);
88  	} else {
89  		paddedSize = nextMultiple(size, 8192);
90  	}
91  	
92  	assert(paddedSize >= size);
93  	return paddedSize - size;
94  }