File: CommonCrypto.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (139 lines) | stat: -rw-r--r-- 4,940 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// CommonCrypto bindings for MonoMac and MonoTouch
//
// Authors:
//	Sebastien Pouliot  <sebastien@xamarin.com>
//
// Copyright 2012-2014 Xamarin Inc.

using System;
using System.Security.Cryptography;
using System.Runtime.InteropServices;

namespace Crimson.CommonCrypto {

	// int32_t -> CommonCryptor.h
	enum CCCryptorStatus {
	    Success			= 0,
    	ParamError		= -4300,
	    BufferTooSmall	= -4301,
    	MemoryFailure	= -4302,
    	AlignmentError	= -4303,
    	DecodeError		= -4304,
    	Unimplemented	= -4305
	}
	
	// uint32_t -> CommonCryptor.h
	// note: not exposed publicly so it can stay signed
	enum CCOperation {
		Encrypt = 0, 
		Decrypt,     
	}

	// uint32_t -> CommonCryptor.h
	// note: not exposed publicly so it can stay signed
	enum CCAlgorithm {
		AES128 = 0,
		DES,        
		TripleDES,       
		CAST,       
		RC4,
		RC2,   
		Blowfish    
	}
	
	// uint32_t -> CommonCryptor.h
	// note: not exposed publicly so it can stay signed
	[Flags]
	enum CCOptions {
		None			= 0,
		PKCS7Padding	= 1,
		ECBMode			= 2
	}
	
	static class Cryptor {
		
		const string libSystem = "/usr/lib/libSystem.dylib";
		
		// size_t was changed to IntPtr for 32/64 bits size difference - even if mono is (moslty) used in 32bits only on OSX today
		// not using `nint` to be able to resue this outside (if needed)
		
		[DllImport (libSystem)]
		extern internal static CCCryptorStatus CCCryptorCreate (CCOperation op, CCAlgorithm alg, CCOptions options, /* const void* */ byte[] key, /* size_t */ IntPtr keyLength, /* const void* */ byte[] iv, /* CCCryptorRef* */ ref IntPtr cryptorRef);

		[DllImport (libSystem)]
		extern internal static CCCryptorStatus CCCryptorRelease (/* CCCryptorRef */ IntPtr cryptorRef);

		[DllImport (libSystem)]
		extern internal static CCCryptorStatus CCCryptorUpdate (/* CCCryptorRef */ IntPtr cryptorRef, /* const void* */ byte[] dataIn, /* size_t */ IntPtr dataInLength, /* void* */ byte[] dataOut, /* size_t */ IntPtr dataOutAvailable, /* size_t* */ ref IntPtr dataOutMoved);

		[DllImport (libSystem)]
		extern internal static CCCryptorStatus CCCryptorUpdate (/* CCCryptorRef */ IntPtr cryptorRef, /* const void* */ IntPtr dataIn, /* size_t */ IntPtr dataInLength, /* void* */ IntPtr dataOut, /* size_t */ IntPtr dataOutAvailable, /* size_t* */ ref IntPtr dataOutMoved);

		[DllImport (libSystem)]
		extern internal static CCCryptorStatus CCCryptorFinal (/* CCCryptorRef */ IntPtr cryptorRef, /* void* */ byte[] dataOut, /* size_t */ IntPtr dataOutAvailable, /* size_t* */ ref IntPtr dataOutMoved);

		[DllImport (libSystem)]
		extern internal static int CCCryptorGetOutputLength (/* CCCryptorRef */ IntPtr cryptorRef, /* size_t */ IntPtr inputLength, bool final);

		[DllImport (libSystem)]
		extern internal static CCCryptorStatus CCCryptorReset (/* CCCryptorRef */ IntPtr cryptorRef, /* const void* */ IntPtr iv);
		
		// helper method to reduce the amount of generate code for each cipher algorithm
		static internal IntPtr Create (CCOperation operation, CCAlgorithm algorithm, CCOptions options, byte[] key, byte[] iv)
		{
			if (key == null)
				throw new CryptographicException ("A null key was provided");
			
			// unlike the .NET framework CommonCrypto does not support two-keys triple-des (128 bits) ref: #6967
			if ((algorithm == CCAlgorithm.TripleDES) && (key.Length == 16)) {
				byte[] key3 = new byte [24];
				Buffer.BlockCopy (key, 0, key3, 0, 16);
				Buffer.BlockCopy (key, 0, key3, 16, 8);
				key = key3;
			}
			
			IntPtr cryptor = IntPtr.Zero;
			CCCryptorStatus status = Cryptor.CCCryptorCreate (operation, algorithm, options, key, (IntPtr) key.Length, iv, ref cryptor);
			if (status != CCCryptorStatus.Success)
				throw new CryptographicUnexpectedOperationException ();
			return cryptor;
		}

		// size_t was changed to IntPtr for 32/64 bits size difference - even if mono is (moslty) used in 32bits only on OSX today
		[DllImport ("/System/Library/Frameworks/Security.framework/Security")]
		unsafe extern internal static /* int */ int SecRandomCopyBytes (/* SecRandomRef */ IntPtr rnd, /* size_t */ IntPtr count, /* uint8_t* */ byte *data);
		
		unsafe static internal void GetRandom (byte[] buffer)
		{
			fixed (byte* fixed_bytes = buffer) {
				if (SecRandomCopyBytes (IntPtr.Zero, (IntPtr)buffer.Length, fixed_bytes) != 0)
					throw new CryptographicException (Marshal.GetLastWin32Error ()); // errno
			}
		}

		static internal unsafe void GetRandom (byte* data, IntPtr data_length)
		{
			if (SecRandomCopyBytes (IntPtr.Zero, data_length, data) != 0)
				throw new CryptographicException (Marshal.GetLastWin32Error ()); // errno
		}

	}
	
#if !MONOTOUCH && !XAMMAC
	static class KeyBuilder {
		static public byte[] Key (int size) 
		{
			byte[] buffer = new byte [size];
			Cryptor.GetRandom (buffer);
			return buffer;
		}
	
		static public byte[] IV (int size) 
		{
			byte[] buffer = new byte [size];
			Cryptor.GetRandom (buffer);
			return buffer;
		}
	}
#endif
}