OSDP.Net 5.2.1
A .NET library for implementing the Open Supervised Device Protocol (OSDP)
Loading...
Searching...
No Matches
SecurityContext.cs
1using System;
2using System.Security.Cryptography;
3
5
12public class SecurityContext
13{
14 private byte[] _securityKey = DefaultKey;
15
19 internal static readonly byte[] DefaultKey = "0123456789:;<=>?"u8.ToArray();
20
24 public SecurityContext(byte[] securityKey = null) => Reset(securityKey);
25
34 public void Reset(byte[] securityKey = null)
35 {
36 if (securityKey != null)
37 {
38 _securityKey = securityKey;
39 }
40
41 IsUsingDefaultKey = !(_securityKey != null && !_securityKey.SequenceEqual(DefaultKey));
42 IsInitialized = false;
43 IsSecurityEstablished = false;
44 new Random().NextBytes(ServerRandomNumber);
45 }
46
58 internal void UpdateSecurityKey(byte[] securityKey)
59 {
60 if (securityKey == null)
61 {
62 return;
63 }
64
65 _securityKey = securityKey;
66 IsUsingDefaultKey = _securityKey.SequenceEqual(DefaultKey);
67 }
68
72 internal bool IsSecurityEstablished { get; set; }
73
77 internal byte[] Enc { get; set; } = Array.Empty<byte>();
78
82 internal byte[] SMac1 { get; set; } = Array.Empty<byte>();
83
87 internal byte[] SMac2 { get; set; } = Array.Empty<byte>();
88
92 internal byte[] RMac { get; set; } = Array.Empty<byte>();
93
97 internal byte[] CMac { get; set; } = Array.Empty<byte>();
98
102 internal byte[] ServerCryptogram { get; private set; }
103
114 internal byte[] ServerRandomNumber { get; } = new byte[8];
115
122 public bool IsInitialized { get; private set; }
123
135 public bool IsUsingDefaultKey { get; internal set; }
136
146 internal Aes CreateCypher(bool isForSessionSetup, byte[] key = null)
147 {
148 var crypto = Aes.Create();
149 if (crypto == null)
150 {
151 throw new Exception("Unable to create AES algorithm");
152 }
153
154 if (!isForSessionSetup)
155 {
156 crypto.Mode = CipherMode.CBC;
157 crypto.Padding = PaddingMode.None;
158 }
159 else
160 {
161 crypto.Mode = CipherMode.ECB;
162 crypto.Padding = PaddingMode.Zeros;
163 }
164
165 crypto.KeySize = 128;
166 crypto.BlockSize = 128;
167 crypto.Key = key ?? _securityKey;
168
169 return crypto;
170 }
171
179 internal static byte[] GenerateKey(Aes aes, byte[] input)
180 {
181 var buffer = new byte[16];
182 input.CopyTo(buffer, 0);
183
184 using var encryptor = aes.CreateEncryptor();
185 return encryptor.TransformFinalBlock(buffer, 0, buffer.Length);
186 }
187
197 internal static byte[] GenerateKey(Aes aes, byte[] input1, byte[] input2)
198 {
199 var buffer = new byte[16];
200 input1.CopyTo(buffer, 0);
201 input2.CopyTo(buffer, input1.Length);
202
203 using var encryptor = aes.CreateEncryptor();
204 return encryptor.TransformFinalBlock(buffer, 0, buffer.Length);
205 }
206
213 internal void InitializeACU(byte[] clientRandomNumber, byte[] clientCryptogram)
214 {
215 using var keyAlgorithm = CreateCypher(true);
216 Enc = GenerateKey(keyAlgorithm, new byte[]
217 {
218 0x01, 0x82, ServerRandomNumber[0], ServerRandomNumber[1], ServerRandomNumber[2],
219 ServerRandomNumber[3], ServerRandomNumber[4], ServerRandomNumber[5]
220 });
221
222 using var serverCypher = CreateCypher(true, Enc);
223 if (!clientCryptogram.SequenceEqual(GenerateKey(serverCypher,
224 ServerRandomNumber, clientRandomNumber)))
225 {
226 throw new Exception("Invalid client cryptogram");
227 }
228
229 SMac1 = GenerateKey(keyAlgorithm,
230 new byte[]
231 {
232 0x01, 0x01, ServerRandomNumber[0], ServerRandomNumber[1], ServerRandomNumber[2],
233 ServerRandomNumber[3], ServerRandomNumber[4], ServerRandomNumber[5]
234 });
235 SMac2 = GenerateKey(keyAlgorithm,
236 new byte[]
237 {
238 0x01, 0x02, ServerRandomNumber[0], ServerRandomNumber[1], ServerRandomNumber[2],
239 ServerRandomNumber[3], ServerRandomNumber[4], ServerRandomNumber[5]
240 });
241
242 ServerCryptogram = GenerateKey(serverCypher, clientRandomNumber, ServerRandomNumber);
243 IsInitialized = true;
244 }
245
246 internal void Establish(byte[] rmac)
247 {
248 RMac = rmac;
249 IsSecurityEstablished = true;
250 }
251}
bool IsUsingDefaultKey
Gets a value indicating whether the security context is using the default key.
void Reset(byte[] securityKey=null)
Resets secure channel back to its initial state.
bool IsInitialized
Gets a value indicating whether the security context is initialized.
SecurityContext(byte[] securityKey=null)
Represents a security context for OSDP secure channel.