1use core::cell::Cell;
27use kernel::debug;
28use kernel::hil::i2c::{self, I2CClient, I2CDevice};
29use kernel::hil::public_key_crypto::keys;
30use kernel::hil::public_key_crypto::signature::{ClientVerify, SignatureVerify};
31use kernel::hil::{digest, entropy, entropy::Entropy32};
32use kernel::utilities::cells::{MapCell, OptionalCell, TakeCell};
33use kernel::utilities::leasable_buffer::{SubSlice, SubSliceMut, SubSliceMutImmut};
34use kernel::ErrorCode;
35
36const RESPONSE_COUNT_SIZE: usize = 1;
38const RESPONSE_SIGNAL_SIZE: usize = 1;
39const RESPONSE_SHA_SIZE: usize = 32;
40#[allow(dead_code)]
41const RESPONSE_INFO_SIZE: usize = 4;
42const RESPONSE_RANDOM_SIZE: usize = 32;
43const CRC_SIZE: usize = 2;
44#[allow(dead_code)]
45const CONFIG_ZONE_SIZE: usize = 128;
46#[allow(dead_code)]
47const SERIAL_NUMBER_SIZE: usize = 10;
48
49const ATRCC508A_PROTOCOL_FIELD_COMMAND: usize = 0;
51const ATRCC508A_PROTOCOL_FIELD_LENGTH: usize = 1;
52const ATRCC508A_PROTOCOL_FIELD_OPCODE: usize = 2;
53const ATRCC508A_PROTOCOL_FIELD_PARAM1: usize = 3;
54const ATRCC508A_PROTOCOL_FIELD_PARAM2: usize = 4;
55const ATRCC508A_PROTOCOL_FIELD_DATA: usize = 6;
56
57const ATRCC508A_PROTOCOL_FIELD_SIZE_COMMAND: usize = 1;
59const ATRCC508A_PROTOCOL_FIELD_SIZE_LENGTH: usize = 1;
60const ATRCC508A_PROTOCOL_FIELD_SIZE_OPCODE: usize = 1;
61const ATRCC508A_PROTOCOL_FIELD_SIZE_PARAM1: usize = 1;
62const ATRCC508A_PROTOCOL_FIELD_SIZE_PARAM2: usize = 2;
63const ATRCC508A_PROTOCOL_FIELD_SIZE_CRC: usize = CRC_SIZE;
64
65const ZONE_CONFIG: u8 = 0x00;
66#[allow(dead_code)]
67const ZONE_OTP: u8 = 0x01;
68#[allow(dead_code)]
69const ZONE_DATA: u8 = 0x02;
70
71const ADDRESS_CONFIG_READ_BLOCK_0: u16 = 0x0000; #[allow(dead_code)]
73const ADDRESS_CONFIG_READ_BLOCK_1: u16 = 0x0008; const ADDRESS_CONFIG_READ_BLOCK_2: u16 = 0x0010; #[allow(dead_code)]
76const ADDRESS_CONFIG_READ_BLOCK_3: u16 = 0x0018; const CONFIG_ZONE_READ_SIZE: usize = 32;
80#[allow(dead_code)]
81const CONFIG_ZONE_SLOT_CONFIG: usize = 20;
82const CONFIG_ZONE_OTP_LOCK: usize = 86;
83const CONFIG_ZONE_LOCK_STATUS: usize = 87;
84const CONFIG_ZONE_SLOTS_LOCK0: usize = 88;
85const CONFIG_ZONE_SLOTS_LOCK1: usize = 89;
86#[allow(dead_code)]
87const CONFIG_ZONE_KEY_CONFIG: usize = 96;
88
89#[allow(dead_code)]
91const COMMAND_OPCODE_INFO: u8 = 0x30; const COMMAND_OPCODE_LOCK: u8 = 0x17; const COMMAND_OPCODE_RANDOM: u8 = 0x1B; const COMMAND_OPCODE_READ: u8 = 0x02; #[allow(dead_code)]
96const COMMAND_OPCODE_WRITE: u8 = 0x12; const COMMAND_OPCODE_SHA: u8 = 0x47; #[allow(dead_code)]
99const COMMAND_OPCODE_GENKEY: u8 = 0x40; #[allow(dead_code)]
101const COMMAND_OPCODE_NONCE: u8 = 0x16; #[allow(dead_code)]
103const COMMAND_OPCODE_SIGN: u8 = 0x41; #[allow(dead_code)]
105const COMMAND_OPCODE_VERIFY: u8 = 0x45; const VERIFY_MODE_EXTERNAL: u8 = 0x02; #[allow(dead_code)]
109const VERIFY_MODE_STORED: u8 = 0b00000000; const VERIFY_PARAM2_KEYTYPE_ECC: u8 = 0x0004; #[allow(dead_code)]
112const VERIFY_PARAM2_KEYTYPE_NONECC: u8 = 0x0007; const NONCE_MODE_PASSTHROUGH: u8 = 0b00000011; const LOCK_MODE_ZONE_CONFIG: u8 = 0b10000000;
116const LOCK_MODE_ZONE_DATA_AND_OTP: u8 = 0b10000001;
117const LOCK_MODE_SLOT0: u8 = 0b10000010;
118
119#[allow(dead_code)]
120const RANDOM_BYTES_BLOCK_SIZE: usize = 32;
121
122const SHA_START: u8 = 0;
123const SHA_UPDATE: u8 = 1;
124const SHA_END: u8 = 2;
125
126#[allow(dead_code)]
127const SHA256_SIZE: usize = 32;
128const PUBLIC_KEY_SIZE: usize = 64;
129#[allow(dead_code)]
130const SIGNATURE_SIZE: usize = 64;
131#[allow(dead_code)]
132const BUFFER_SIZE: usize = 128;
133
134const RESPONSE_SIGNAL_INDEX: usize = RESPONSE_COUNT_SIZE;
135const ATRCC508A_SUCCESSFUL_TEMPKEY: u8 = 0x00;
136const ATRCC508A_SUCCESSFUL_VERIFY: u8 = 0x00;
137const ATRCC508A_SUCCESSFUL_LOCK: u8 = 0x00;
138
139const WORD_ADDRESS_VALUE_RESET: u8 = 0x00;
140const WORD_ADDRESS_VALUE_IDLE: u8 = 0x02;
141const WORD_ADDRESS_VALUE_COMMAND: u8 = 0x03;
142
143const ATRCC508A_PROTOCOL_OVERHEAD: usize = ATRCC508A_PROTOCOL_FIELD_SIZE_COMMAND
144 + ATRCC508A_PROTOCOL_FIELD_SIZE_LENGTH
145 + ATRCC508A_PROTOCOL_FIELD_SIZE_OPCODE
146 + ATRCC508A_PROTOCOL_FIELD_SIZE_PARAM1
147 + ATRCC508A_PROTOCOL_FIELD_SIZE_PARAM2
148 + ATRCC508A_PROTOCOL_FIELD_SIZE_CRC;
149
150#[allow(dead_code)]
151const GENKEY_MODE_PUBLIC: u8 = 0b00000000;
152const GENKEY_MODE_NEW_PRIVATE: u8 = 0b00000100;
153
154#[derive(Clone, Copy, Debug, PartialEq)]
155enum Operation {
156 Reset,
157 Ready,
158 ReadConfigZeroCommand,
159 ReadConfigZeroResult(usize),
160 ReadConfigTwoCommand,
161 ReadConfigTwoResult(usize),
162 GenerateEntropyCommand(usize),
163 GenerateEntropyResult(usize),
164 SetupConfigOne,
165 SetupConfigTwo(usize),
166 LockZoneConfig(usize),
167 LockResponse(usize),
168 CreateKeyPair(usize, u16),
169 ReadKeyPair(usize),
170 LockDataOtp(usize),
171 LockSlot0(usize),
172 StartSha(usize),
173 ShaLoad(usize),
174 ShaLoadResponse(usize),
175 ReadySha,
176 ShaRun(usize),
177 ShaEnd(usize),
178 LoadTempKeyNonce(usize),
179 LoadTempKeyCheckNonce(usize),
180 VerifySubmitData(usize),
181 CompleteVerify(usize),
182}
183
184pub struct Atecc508a<'a> {
185 buffer: TakeCell<'static, [u8]>,
186 i2c: &'a dyn I2CDevice,
187 op: Cell<Operation>,
188 op_len: Cell<usize>,
189
190 entropy_buffer: TakeCell<'static, [u8; 32]>,
191 entropy_offset: Cell<usize>,
192 entropy_client: OptionalCell<&'a dyn entropy::Client32>,
193
194 digest_client: OptionalCell<&'a dyn digest::ClientDataHash<32>>,
195 digest_buffer: TakeCell<'static, [u8; 64]>,
196 write_len: Cell<usize>,
197 remain_len: Cell<usize>,
198 hash_data: MapCell<SubSliceMutImmut<'static, u8>>,
199 digest_data: TakeCell<'static, [u8; 32]>,
200
201 secure_client: OptionalCell<&'a dyn ClientVerify<32, 64>>,
202 message_data: TakeCell<'static, [u8; 32]>,
203 signature_data: TakeCell<'static, [u8; 64]>,
204 ext_public_key: TakeCell<'static, [u8; 64]>,
205 ext_public_key_temp: TakeCell<'static, [u8; 64]>,
206 key_set_client: OptionalCell<&'a dyn keys::SetKeyBySliceClient<64>>,
207 deferred_call: kernel::deferred_call::DeferredCall,
208
209 wakeup_device: fn(),
210
211 config_lock: Cell<bool>,
212 data_lock: Cell<bool>,
213 public_key: OptionalCell<[u8; PUBLIC_KEY_SIZE]>,
214}
215
216impl<'a> Atecc508a<'a> {
217 pub fn new(
218 i2c: &'a dyn I2CDevice,
219 buffer: &'static mut [u8],
220 entropy_buffer: &'static mut [u8; 32],
221 digest_buffer: &'static mut [u8; 64],
222 wakeup_device: fn(),
223 ) -> Self {
224 Atecc508a {
225 buffer: TakeCell::new(buffer),
226 i2c,
227 op: Cell::new(Operation::Ready),
228 op_len: Cell::new(0),
229 entropy_buffer: TakeCell::new(entropy_buffer),
230 entropy_offset: Cell::new(0),
231 entropy_client: OptionalCell::empty(),
232 digest_client: OptionalCell::empty(),
233 digest_buffer: TakeCell::new(digest_buffer),
234 write_len: Cell::new(0),
235 remain_len: Cell::new(0),
236 hash_data: MapCell::empty(),
237 digest_data: TakeCell::empty(),
238 secure_client: OptionalCell::empty(),
239 message_data: TakeCell::empty(),
240 signature_data: TakeCell::empty(),
241 ext_public_key: TakeCell::empty(),
242 ext_public_key_temp: TakeCell::empty(),
243 key_set_client: OptionalCell::empty(),
244 deferred_call: kernel::deferred_call::DeferredCall::new(),
245 wakeup_device,
246 config_lock: Cell::new(false),
247 data_lock: Cell::new(false),
248 public_key: OptionalCell::new([0; PUBLIC_KEY_SIZE]),
249 }
250 }
251
252 fn calculate_crc(data: &[u8]) -> u16 {
253 let mut crc_register: u16 = 0;
254
255 for counter in 0..data.len() {
256 let mut shift_register: u8 = 0x01;
257
258 while shift_register > 0x00 {
259 let data_val = data[counter] & shift_register;
260 let data_bit = u16::from(data_val > 0);
261
262 let crc_bit = crc_register >> 15;
263 crc_register <<= 1;
264
265 if data_bit != crc_bit {
266 crc_register ^= 0x8005;
267 }
268
269 shift_register <<= 1;
270 }
271 }
272
273 crc_register
274 }
275
276 fn read(&self, zone: u8, address: u16, length: usize) -> Result<(), ErrorCode> {
277 let mut zone_calc = zone;
278
279 match length {
280 32 => zone_calc |= 1 << 7,
281 4 => zone_calc &= !(1 << 7),
282 _ => return Err(ErrorCode::SIZE),
283 }
284
285 self.op_len.set(length);
286
287 self.send_command(COMMAND_OPCODE_READ, zone_calc, address, 0);
288
289 Ok(())
290 }
291
292 fn write(&self, zone: u8, address: u16, length: usize) -> Result<(), ErrorCode> {
293 let mut zone_calc = zone;
294
295 match length {
296 32 => zone_calc |= 1 << 7,
297 4 => zone_calc &= !(1 << 7),
298 _ => return Err(ErrorCode::SIZE),
299 }
300
301 self.op_len.set(length);
302
303 self.send_command(COMMAND_OPCODE_WRITE, zone_calc, address, length);
304
305 Ok(())
306 }
307
308 fn idle(&self) {
309 self.buffer.take().map(|buffer| {
310 buffer[ATRCC508A_PROTOCOL_FIELD_COMMAND] = WORD_ADDRESS_VALUE_IDLE;
311
312 let _ = self.i2c.write(buffer, 1);
313 });
314 }
315
316 fn reset(&self) {
317 self.buffer.take().map(|buffer| {
318 self.op.set(Operation::Reset);
319
320 buffer[ATRCC508A_PROTOCOL_FIELD_COMMAND] = WORD_ADDRESS_VALUE_RESET;
321
322 let _ = self.i2c.write(buffer, 1);
323 });
324 }
325
326 fn send_command(&self, command_opcode: u8, param1: u8, param2: u16, length: usize) {
327 let i2c_length = length + ATRCC508A_PROTOCOL_OVERHEAD;
328
329 self.buffer.take().map(|buffer| {
330 buffer[ATRCC508A_PROTOCOL_FIELD_COMMAND] = WORD_ADDRESS_VALUE_COMMAND;
331 buffer[ATRCC508A_PROTOCOL_FIELD_LENGTH] =
332 (i2c_length - ATRCC508A_PROTOCOL_FIELD_SIZE_LENGTH) as u8;
333 buffer[ATRCC508A_PROTOCOL_FIELD_OPCODE] = command_opcode;
334 buffer[ATRCC508A_PROTOCOL_FIELD_PARAM1] = param1;
335 buffer[ATRCC508A_PROTOCOL_FIELD_PARAM2] = (param2 & 0xFF) as u8;
336 buffer[ATRCC508A_PROTOCOL_FIELD_PARAM2 + 1] = ((param2 >> 8) & 0xFF) as u8;
337
338 let data_crc_len = i2c_length
339 - (ATRCC508A_PROTOCOL_FIELD_SIZE_COMMAND + ATRCC508A_PROTOCOL_FIELD_SIZE_CRC);
340 let crc = Self::calculate_crc(
341 &buffer[ATRCC508A_PROTOCOL_FIELD_LENGTH
342 ..(data_crc_len + ATRCC508A_PROTOCOL_FIELD_LENGTH)],
343 );
344
345 buffer[i2c_length - ATRCC508A_PROTOCOL_FIELD_SIZE_CRC] = (crc & 0xFF) as u8;
346 buffer[i2c_length - ATRCC508A_PROTOCOL_FIELD_SIZE_CRC + 1] = ((crc >> 8) & 0xFF) as u8;
347
348 let _ = self.i2c.write(buffer, i2c_length);
349 });
350 }
351
352 pub fn read_config_zone(&self) -> Result<(), ErrorCode> {
355 assert_eq!(self.op.get(), Operation::Ready);
356
357 self.op.set(Operation::ReadConfigZeroCommand);
358
359 (self.wakeup_device)();
360
361 self.read(
362 ZONE_CONFIG,
363 ADDRESS_CONFIG_READ_BLOCK_0,
364 CONFIG_ZONE_READ_SIZE,
365 )
366 }
367
368 pub fn setup_tock_config(&self) -> Result<(), ErrorCode> {
404 self.op.set(Operation::SetupConfigOne);
405
406 (self.wakeup_device)();
407
408 self.buffer.take().map(|buffer| {
410 buffer[ATRCC508A_PROTOCOL_FIELD_DATA..(ATRCC508A_PROTOCOL_FIELD_DATA + 4)]
411 .copy_from_slice(&[0x33, 0x00, 0x33, 0x00]);
412
413 self.buffer.replace(buffer);
414 });
415
416 self.write(ZONE_CONFIG, 96 / 4, 4)?;
417
418 Ok(())
419 }
420
421 pub fn lock_zone_config(&self) -> Result<(), ErrorCode> {
423 self.op.set(Operation::LockZoneConfig(0));
424
425 self.send_command(COMMAND_OPCODE_LOCK, LOCK_MODE_ZONE_CONFIG, 0x0000, 0);
426
427 Ok(())
428 }
429
430 pub fn create_key_pair(&self, slot: u16) -> Result<(), ErrorCode> {
432 self.op.set(Operation::CreateKeyPair(0, slot));
433
434 (self.wakeup_device)();
435
436 self.send_command(COMMAND_OPCODE_GENKEY, GENKEY_MODE_NEW_PRIVATE, slot, 0);
437
438 Ok(())
439 }
440
441 pub fn get_public_key(
445 &'a self,
446 _slot: u16,
447 ) -> Result<&'a OptionalCell<[u8; PUBLIC_KEY_SIZE]>, ErrorCode> {
448 if self.public_key.get().unwrap().iter().all(|&x| x == 0) {
449 return Err(ErrorCode::BUSY);
450 }
451
452 Ok(&self.public_key)
453 }
454
455 pub fn set_public_key(
461 &self,
462 public_key: Option<&'static mut [u8; 64]>,
463 ) -> Option<&'static mut [u8; 64]> {
464 let ret = self.ext_public_key.take();
465
466 if let Some(key) = public_key {
467 self.ext_public_key.replace(key);
468 }
469
470 ret
471 }
472
473 pub fn lock_data_and_otp(&self) -> Result<(), ErrorCode> {
475 self.op.set(Operation::LockDataOtp(0));
476
477 (self.wakeup_device)();
478
479 self.send_command(COMMAND_OPCODE_LOCK, LOCK_MODE_ZONE_DATA_AND_OTP, 0x0000, 0);
480
481 Ok(())
482 }
483
484 pub fn lock_slot0(&self) -> Result<(), ErrorCode> {
486 self.op.set(Operation::LockSlot0(0));
487
488 (self.wakeup_device)();
489
490 self.send_command(COMMAND_OPCODE_LOCK, LOCK_MODE_SLOT0, 0x0000, 0);
491
492 Ok(())
493 }
494
495 pub fn device_locked(&self) -> bool {
497 self.config_lock.get() && self.data_lock.get()
498 }
499
500 fn sha_update(&self) -> bool {
501 let op_len = (self.hash_data.map_or(0, |buf| match buf {
502 SubSliceMutImmut::Mutable(b) => {
503 let len = b.len();
504 self.remain_len.get() + len
505 }
506 SubSliceMutImmut::Immutable(b) => {
507 let len = b.len();
508 self.remain_len.get() + len
509 }
510 }))
511 .min(64);
512
513 if op_len < 64 {
517 self.op.set(Operation::ReadySha);
518
519 self.hash_data.map(|buf| {
520 if op_len > 0 {
521 self.digest_buffer.map(|digest_buffer| {
522 digest_buffer[self.remain_len.get()..(self.remain_len.get() + op_len)]
523 .copy_from_slice(&buf[0..op_len]);
524
525 self.remain_len.set(self.remain_len.get() + op_len);
526
527 buf.slice(op_len..);
528 });
529 }
530
531 self.idle();
532 });
533
534 return false;
535 }
536
537 self.buffer.take().map(|buffer| {
539 let remain_len = self.remain_len.get();
540
541 if remain_len > 0 {
542 self.digest_buffer.map(|digest_buffer| {
543 buffer[ATRCC508A_PROTOCOL_FIELD_DATA
544 ..(ATRCC508A_PROTOCOL_FIELD_DATA + remain_len)]
545 .copy_from_slice(&digest_buffer[0..remain_len]);
546 });
547 }
548
549 self.hash_data.map(|hash_data| {
550 buffer[ATRCC508A_PROTOCOL_FIELD_DATA + remain_len
551 ..(ATRCC508A_PROTOCOL_FIELD_DATA + op_len)]
552 .copy_from_slice(&hash_data[0..(op_len - remain_len)]);
553
554 hash_data.slice((op_len - remain_len)..);
555 });
556
557 self.remain_len.set(0);
558 self.buffer.replace(buffer);
559 });
560
561 self.op.set(Operation::ShaLoadResponse(0));
562
563 true
564 }
565}
566
567impl I2CClient for Atecc508a<'_> {
568 fn command_complete(&self, buffer: &'static mut [u8], status: Result<(), i2c::Error>) {
569 match self.op.get() {
570 Operation::Ready => unreachable!(),
571 Operation::ReadySha => {
572 self.buffer.replace(buffer);
573
574 self.hash_data.take().map(|buf| {
575 self.digest_client.map(|client| match buf {
576 SubSliceMutImmut::Mutable(b) => client.add_mut_data_done(Ok(()), b),
577 SubSliceMutImmut::Immutable(b) => client.add_data_done(Ok(()), b),
578 })
579 });
580 }
581 Operation::Reset => {
582 self.buffer.replace(buffer);
583 }
584 Operation::ReadConfigZeroCommand => {
585 self.op.set(Operation::ReadConfigZeroResult(0));
586
587 let _ = self
588 .i2c
589 .read(buffer, self.op_len.get() + RESPONSE_COUNT_SIZE + CRC_SIZE);
590 }
591 Operation::ReadConfigZeroResult(run) => {
592 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
593 if run == 10 {
595 return;
596 }
597
598 self.op.set(Operation::ReadConfigZeroResult(run + 1));
599
600 let _ = self
601 .i2c
602 .read(buffer, self.op_len.get() + RESPONSE_COUNT_SIZE + CRC_SIZE);
603
604 return;
605 }
606
607 self.op.set(Operation::ReadConfigTwoCommand);
608
609 assert_eq!(status, Ok(()));
610
611 let mut serial_num: [u8; 9] = [0; 9];
612 serial_num[0..3].copy_from_slice(&buffer[0..3]);
613 serial_num[4..8].copy_from_slice(&buffer[8..12]);
614
615 debug!("ATECC508A Serial Number: {serial_num:x?}");
616 debug!("ATECC508A Rev Number: {:x?}", &buffer[4..7]);
617
618 self.buffer.replace(buffer);
619
620 let _ = self.read(
621 ZONE_CONFIG,
622 ADDRESS_CONFIG_READ_BLOCK_2,
623 CONFIG_ZONE_READ_SIZE,
624 );
625 }
626 Operation::ReadConfigTwoCommand => {
627 self.op.set(Operation::ReadConfigTwoResult(0));
628
629 let _ = self
630 .i2c
631 .read(buffer, self.op_len.get() + RESPONSE_COUNT_SIZE + CRC_SIZE);
632 }
633 Operation::ReadConfigTwoResult(run) => {
634 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
635 if run == 10 {
637 return;
638 }
639
640 self.op.set(Operation::ReadConfigTwoResult(run + 1));
641
642 let _ = self
643 .i2c
644 .read(buffer, self.op_len.get() + RESPONSE_COUNT_SIZE + CRC_SIZE);
645
646 return;
647 }
648
649 self.op.set(Operation::Ready);
650
651 assert_eq!(status, Ok(()));
652
653 let otp_lock = buffer[CONFIG_ZONE_OTP_LOCK - 63];
654 if otp_lock == 0x55 {
655 debug!("ATECC508A Data and OTP UnLocked");
656 } else if otp_lock == 0x00 {
657 debug!("ATECC508A Data and OTP Locked");
658 self.data_lock.set(true);
659 } else {
660 debug!("ATECC508A Data and OTP Invalid Config");
661 }
662
663 let config_lock = buffer[CONFIG_ZONE_LOCK_STATUS - 63];
664 if config_lock == 0x55 {
665 debug!("ATECC508A Config Zone UnLocked");
666 } else if config_lock == 0x00 {
667 debug!("ATECC508A Config Zone Locked");
668 self.config_lock.set(true);
669 } else {
670 debug!("ATECC508A Config Zone Invalid Config");
671 }
672
673 debug!(
674 "ATECC508A Slot Lock Status: 0x{:x} and 0x{:x}",
675 &buffer[CONFIG_ZONE_SLOTS_LOCK0 - 63],
676 &buffer[CONFIG_ZONE_SLOTS_LOCK1 - 63]
677 );
678
679 self.buffer.replace(buffer);
680 }
681 Operation::GenerateEntropyCommand(run) => {
682 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
683 self.buffer.replace(buffer);
684
685 if run == 10 {
687 self.entropy_client.map(move |client| {
688 client.entropy_available(
689 &mut Atecc508aRngIter(self),
690 Err(ErrorCode::NOACK),
691 );
692 });
693
694 return;
695 }
696
697 self.op.set(Operation::GenerateEntropyCommand(run + 1));
698 self.send_command(COMMAND_OPCODE_RANDOM, 0x00, 0x0000, 0);
699
700 return;
701 }
702
703 self.op.set(Operation::GenerateEntropyResult(0));
704
705 let _ = self.i2c.read(
706 buffer,
707 RESPONSE_COUNT_SIZE + RESPONSE_RANDOM_SIZE + CRC_SIZE,
708 );
709 }
710 Operation::GenerateEntropyResult(run) => {
711 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
712 if run == 1000 {
715 self.entropy_client.map(move |client| {
716 client.entropy_available(
717 &mut Atecc508aRngIter(self),
718 Err(ErrorCode::NOACK),
719 );
720 });
721
722 return;
723 }
724
725 self.op.set(Operation::GenerateEntropyResult(run + 1));
726
727 let _ = self.i2c.read(
728 buffer,
729 RESPONSE_COUNT_SIZE + RESPONSE_RANDOM_SIZE + CRC_SIZE,
730 );
731
732 return;
733 }
734
735 self.op.set(Operation::Ready);
736
737 self.entropy_buffer.take().map(|entropy_buffer| {
738 entropy_buffer.copy_from_slice(
739 &buffer[RESPONSE_COUNT_SIZE..(RESPONSE_COUNT_SIZE + RESPONSE_RANDOM_SIZE)],
740 );
741
742 self.entropy_buffer.replace(entropy_buffer);
743 });
744
745 self.buffer.replace(buffer);
746
747 if self.entropy_client.map(move |client| {
748 client.entropy_available(&mut Atecc508aRngIter(self), Ok(()))
749 }) == Some(entropy::Continue::More)
750 {
751 if let Err(e) = self.get() {
753 self.entropy_client.map(move |client| {
754 client.entropy_available(&mut (0..0), Err(e));
755 });
756 }
757 }
758 }
759 Operation::SetupConfigOne => {
760 self.op.set(Operation::SetupConfigTwo(0));
761
762 self.buffer.replace(buffer);
763
764 self.buffer.take().map(|buffer| {
766 buffer[ATRCC508A_PROTOCOL_FIELD_DATA..(ATRCC508A_PROTOCOL_FIELD_DATA + 4)]
767 .copy_from_slice(&[0x83, 0x20, 0x83, 0x20]);
768
769 self.buffer.replace(buffer);
770 });
771
772 let _ = self.write(ZONE_CONFIG, 20 / 4, 4);
773 }
774 Operation::SetupConfigTwo(run) => {
775 self.buffer.replace(buffer);
776
777 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
778 if run == 10 {
780 self.op.set(Operation::Ready);
781 return;
782 }
783
784 self.op.set(Operation::SetupConfigTwo(run + 1));
785 let _ = self.write(ZONE_CONFIG, 20 / 4, 4);
786 return;
787 }
788
789 self.op.set(Operation::Ready);
790 }
791 Operation::LockZoneConfig(run) => {
792 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
793 self.buffer.replace(buffer);
794
795 if run == 30 {
797 self.op.set(Operation::Ready);
798 return;
799 }
800
801 self.op.set(Operation::LockZoneConfig(run + 1));
802 self.send_command(COMMAND_OPCODE_LOCK, LOCK_MODE_ZONE_CONFIG, 0x0000, 0);
803 return;
804 }
805
806 self.op.set(Operation::LockResponse(0));
807
808 let _ = self.i2c.read(
809 buffer,
810 RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE,
811 );
812 }
813 Operation::LockResponse(run) => {
814 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
815 if run == 100 {
817 self.buffer.replace(buffer);
818 self.op.set(Operation::Ready);
819 return;
820 }
821
822 self.op.set(Operation::LockResponse(run + 1));
823 let _ = self.i2c.read(
824 buffer,
825 RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE,
826 );
827 return;
828 }
829
830 self.op.set(Operation::Ready);
831
832 let response = buffer[RESPONSE_SIGNAL_INDEX];
833
834 if response != ATRCC508A_SUCCESSFUL_LOCK {
835 debug!("Failed to lock the device");
836 }
837
838 self.buffer.replace(buffer);
839 }
840 Operation::CreateKeyPair(run, slot) => {
841 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
842 self.buffer.replace(buffer);
843
844 if run == 10 {
846 self.op.set(Operation::Ready);
847 return;
848 }
849
850 self.op.set(Operation::CreateKeyPair(run + 1, slot));
851 self.send_command(COMMAND_OPCODE_GENKEY, GENKEY_MODE_NEW_PRIVATE, slot, 0);
852 return;
853 }
854
855 self.op.set(Operation::ReadKeyPair(0));
856
857 let _ = self
858 .i2c
859 .read(buffer, RESPONSE_COUNT_SIZE + PUBLIC_KEY_SIZE + CRC_SIZE);
860 }
861 Operation::ReadKeyPair(run) => {
862 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
863 if run == 5000 {
866 self.buffer.replace(buffer);
867 self.op.set(Operation::Ready);
868 return;
869 }
870
871 self.op.set(Operation::ReadKeyPair(run + 1));
872 let _ = self
873 .i2c
874 .read(buffer, RESPONSE_COUNT_SIZE + PUBLIC_KEY_SIZE + CRC_SIZE);
875 return;
876 }
877
878 self.public_key.take().map(|mut pub_key| {
879 pub_key.copy_from_slice(
880 &buffer[RESPONSE_COUNT_SIZE..(RESPONSE_COUNT_SIZE + PUBLIC_KEY_SIZE)],
881 );
882 self.public_key.set(pub_key);
883 });
884
885 self.op.set(Operation::Ready);
886 self.buffer.replace(buffer);
887 }
888 Operation::LockDataOtp(run) => {
889 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
890 self.buffer.replace(buffer);
891
892 if run == 100 {
894 self.op.set(Operation::Ready);
895 return;
896 }
897
898 self.op.set(Operation::LockDataOtp(run + 1));
899 self.send_command(COMMAND_OPCODE_LOCK, LOCK_MODE_ZONE_DATA_AND_OTP, 0x0000, 0);
900 return;
901 }
902
903 self.op.set(Operation::LockResponse(0));
904
905 let _ = self.i2c.read(
906 buffer,
907 RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE,
908 );
909 }
910 Operation::LockSlot0(run) => {
911 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
912 self.buffer.replace(buffer);
913
914 if run == 100 {
916 self.op.set(Operation::Ready);
917 return;
918 }
919
920 self.op.set(Operation::LockSlot0(run + 1));
921 self.send_command(COMMAND_OPCODE_LOCK, LOCK_MODE_SLOT0, 0x0000, 0);
922 return;
923 }
924
925 self.op.set(Operation::LockResponse(0));
926
927 let _ = self.i2c.read(
928 buffer,
929 RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE,
930 );
931 }
932 Operation::StartSha(run) => {
933 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
934 self.buffer.replace(buffer);
935
936 if run == 10 {
938 self.op.set(Operation::Ready);
939 return;
940 }
941
942 self.op.set(Operation::StartSha(run + 1));
943 self.send_command(COMMAND_OPCODE_SHA, SHA_START, 0x0000, 0);
944 return;
945 }
946
947 self.op.set(Operation::ShaLoad(0));
948
949 let _ = self.i2c.read(
950 buffer,
951 RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE,
952 );
953 }
954 Operation::ShaLoad(run) => {
955 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
956 if run == 50 {
958 self.op.set(Operation::Ready);
959 return;
960 }
961
962 self.op.set(Operation::ShaLoad(run + 1));
963 let _ = self.i2c.read(
964 buffer,
965 RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE,
966 );
967 return;
968 }
969
970 self.buffer.replace(buffer);
971
972 if self.sha_update() {
973 self.send_command(COMMAND_OPCODE_SHA, SHA_UPDATE, 64, 64);
974 }
975 }
976 Operation::ShaLoadResponse(run) => {
977 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
978 if run == 10 {
980 self.op.set(Operation::Ready);
981 return;
982 }
983
984 self.op.set(Operation::ShaLoadResponse(run + 1));
985 self.send_command(COMMAND_OPCODE_SHA, SHA_UPDATE, 64, 64);
986
987 return;
988 }
989
990 self.op.set(Operation::ShaLoad(0));
991 let _ = self.i2c.read(
992 buffer,
993 RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE,
994 );
995 }
996 Operation::ShaRun(run) => {
997 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
998 self.buffer.replace(buffer);
999
1000 if run == 10 {
1002 self.op.set(Operation::Ready);
1003 return;
1004 }
1005
1006 self.op.set(Operation::ShaRun(run + 1));
1007 self.send_command(
1008 COMMAND_OPCODE_SHA,
1009 SHA_END,
1010 self.remain_len.get() as u16,
1011 self.remain_len.get(),
1012 );
1013 return;
1014 }
1015
1016 self.op.set(Operation::ShaEnd(0));
1017 self.remain_len.set(0);
1018
1019 let _ = self
1020 .i2c
1021 .read(buffer, RESPONSE_COUNT_SIZE + RESPONSE_SHA_SIZE + CRC_SIZE);
1022 }
1023 Operation::ShaEnd(run) => {
1024 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
1025 if run == 500 {
1027 self.op.set(Operation::Ready);
1028 return;
1029 }
1030
1031 self.op.set(Operation::ShaEnd(run + 1));
1032 let _ = self
1033 .i2c
1034 .read(buffer, RESPONSE_COUNT_SIZE + RESPONSE_SHA_SIZE + CRC_SIZE);
1035 return;
1036 }
1037
1038 self.digest_data.take().map(|digest_data| {
1039 digest_data[0..32]
1040 .copy_from_slice(&buffer[RESPONSE_COUNT_SIZE..(RESPONSE_COUNT_SIZE + 32)]);
1041
1042 self.buffer.replace(buffer);
1043
1044 self.op.set(Operation::Ready);
1045
1046 self.digest_client.map(|client| {
1047 client.hash_done(Ok(()), digest_data);
1048 })
1049 });
1050 }
1051 Operation::LoadTempKeyNonce(run) => {
1052 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
1053 self.buffer.replace(buffer);
1054
1055 if run == 10 {
1057 self.op.set(Operation::Ready);
1058 return;
1059 }
1060
1061 self.op.set(Operation::LoadTempKeyNonce(run + 1));
1062 self.send_command(COMMAND_OPCODE_NONCE, NONCE_MODE_PASSTHROUGH, 0x0000, 32);
1063 return;
1064 }
1065
1066 self.op.set(Operation::LoadTempKeyCheckNonce(0));
1067
1068 let _ = self.i2c.read(
1069 buffer,
1070 RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE,
1071 );
1072 }
1073 Operation::LoadTempKeyCheckNonce(run) => {
1074 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
1075 if run == 10 {
1077 self.op.set(Operation::Ready);
1078 return;
1079 }
1080
1081 self.op.set(Operation::LoadTempKeyCheckNonce(run + 1));
1082 let _ = self.i2c.read(
1083 buffer,
1084 RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE,
1085 );
1086 return;
1087 }
1088
1089 if buffer[RESPONSE_SIGNAL_INDEX] != ATRCC508A_SUCCESSFUL_TEMPKEY {
1090 self.buffer.replace(buffer);
1091
1092 self.secure_client.map(|client| {
1093 client.verification_done(
1094 Err(ErrorCode::FAIL),
1095 self.message_data.take().unwrap(),
1096 self.signature_data.take().unwrap(),
1097 );
1098 });
1099
1100 return;
1101 }
1102
1103 self.signature_data.map(|signature_data| {
1105 buffer[ATRCC508A_PROTOCOL_FIELD_DATA..(ATRCC508A_PROTOCOL_FIELD_DATA + 64)]
1106 .copy_from_slice(signature_data);
1107 });
1108
1109 self.ext_public_key.map(|ext_public_key| {
1111 buffer[(ATRCC508A_PROTOCOL_FIELD_DATA + 64)
1112 ..(ATRCC508A_PROTOCOL_FIELD_DATA + 128)]
1113 .copy_from_slice(ext_public_key);
1114 });
1115
1116 self.buffer.replace(buffer);
1117 self.op.set(Operation::VerifySubmitData(0));
1118
1119 self.send_command(
1120 COMMAND_OPCODE_VERIFY,
1121 VERIFY_MODE_EXTERNAL,
1122 VERIFY_PARAM2_KEYTYPE_ECC as u16,
1123 128,
1124 );
1125 }
1126 Operation::VerifySubmitData(run) => {
1127 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
1128 self.buffer.replace(buffer);
1129
1130 if run == 10 {
1132 self.op.set(Operation::Ready);
1133 return;
1134 }
1135
1136 self.op.set(Operation::VerifySubmitData(run + 1));
1137 self.send_command(
1138 COMMAND_OPCODE_VERIFY,
1139 VERIFY_MODE_EXTERNAL,
1140 VERIFY_PARAM2_KEYTYPE_ECC as u16,
1141 128,
1142 );
1143 return;
1144 }
1145
1146 self.op.set(Operation::CompleteVerify(0));
1147 let _ = self.i2c.read(
1148 buffer,
1149 RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE,
1150 );
1151 }
1152 Operation::CompleteVerify(run) => {
1153 if status == Err(i2c::Error::DataNak) || status == Err(i2c::Error::AddressNak) {
1154 if run == 100 {
1156 self.op.set(Operation::Ready);
1157 return;
1158 }
1159
1160 self.op.set(Operation::CompleteVerify(run + 1));
1161 let _ = self.i2c.read(
1162 buffer,
1163 RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE,
1164 );
1165 return;
1166 }
1167
1168 let ret = buffer[RESPONSE_SIGNAL_INDEX];
1169
1170 self.op.set(Operation::Ready);
1171 self.buffer.replace(buffer);
1172
1173 self.secure_client.map(|client| {
1174 if ret == ATRCC508A_SUCCESSFUL_VERIFY {
1175 client.verification_done(
1176 Ok(true),
1177 self.message_data.take().unwrap(),
1178 self.signature_data.take().unwrap(),
1179 );
1180 } else if ret == 1 {
1181 client.verification_done(
1182 Ok(false),
1183 self.message_data.take().unwrap(),
1184 self.signature_data.take().unwrap(),
1185 );
1186 } else {
1187 client.verification_done(
1188 Err(ErrorCode::FAIL),
1189 self.message_data.take().unwrap(),
1190 self.signature_data.take().unwrap(),
1191 );
1192 }
1193 });
1194 }
1195 }
1196 }
1197}
1198
1199struct Atecc508aRngIter<'a, 'b: 'a>(&'a Atecc508a<'b>);
1200
1201impl Iterator for Atecc508aRngIter<'_, '_> {
1202 type Item = u32;
1203
1204 fn next(&mut self) -> Option<u32> {
1205 self.0.entropy_buffer.take().map(|entropy_buffer| {
1206 let offset = self.0.entropy_offset.get();
1207 let entropy_bytes =
1208 <[u8; 4]>::try_from(&entropy_buffer[(offset + 0)..(offset + 4)]).unwrap();
1209 let entropy: u32 = u32::from_be_bytes(entropy_bytes);
1210
1211 if offset >= 28 {
1212 self.0.entropy_offset.set(0);
1213 } else {
1214 self.0.entropy_offset.set(offset + 4);
1215 }
1216 self.0.entropy_buffer.replace(entropy_buffer);
1217
1218 entropy
1219 })
1220 }
1221}
1222
1223impl<'a> entropy::Entropy32<'a> for Atecc508a<'a> {
1224 fn set_client(&'a self, client: &'a dyn entropy::Client32) {
1225 self.entropy_client.set(client);
1226 }
1227
1228 fn get(&self) -> Result<(), ErrorCode> {
1229 self.op.set(Operation::GenerateEntropyCommand(0));
1230
1231 (self.wakeup_device)();
1232
1233 self.send_command(COMMAND_OPCODE_RANDOM, 0x00, 0x0000, 0);
1234
1235 Ok(())
1236 }
1237
1238 fn cancel(&self) -> Result<(), ErrorCode> {
1239 Ok(())
1240 }
1241}
1242
1243impl<'a> digest::DigestData<'a, 32> for Atecc508a<'a> {
1244 fn set_data_client(&'a self, _client: &'a dyn digest::ClientData<32>) {
1245 unimplemented!()
1246 }
1247
1248 fn add_data(
1249 &self,
1250 data: SubSlice<'static, u8>,
1251 ) -> Result<(), (ErrorCode, SubSlice<'static, u8>)> {
1252 if !(self.op.get() == Operation::Ready || self.op.get() == Operation::ReadySha) {
1253 return Err((ErrorCode::BUSY, data));
1254 }
1255
1256 (self.wakeup_device)();
1257
1258 self.write_len.set(data.len());
1259 self.hash_data.replace(SubSliceMutImmut::Immutable(data));
1260
1261 if self.op.get() == Operation::Ready {
1262 self.op.set(Operation::StartSha(0));
1263
1264 self.send_command(COMMAND_OPCODE_SHA, SHA_START, 0x0000, 0);
1265 } else {
1266 self.op.set(Operation::ShaLoad(0));
1267
1268 if self.sha_update() {
1269 self.send_command(COMMAND_OPCODE_SHA, SHA_UPDATE, 64, 64);
1270 }
1271 }
1272
1273 Ok(())
1274 }
1275
1276 fn add_mut_data(
1277 &self,
1278 data: SubSliceMut<'static, u8>,
1279 ) -> Result<(), (ErrorCode, SubSliceMut<'static, u8>)> {
1280 if !(self.op.get() == Operation::Ready || self.op.get() == Operation::ReadySha) {
1281 return Err((ErrorCode::BUSY, data));
1282 }
1283
1284 self.write_len.set(data.len());
1285 self.hash_data.replace(SubSliceMutImmut::Mutable(data));
1286
1287 if self.op.get() == Operation::Ready {
1288 self.op.set(Operation::StartSha(0));
1289
1290 (self.wakeup_device)();
1291
1292 self.send_command(COMMAND_OPCODE_SHA, SHA_START, 0x0000, 0);
1293 } else {
1294 self.op.set(Operation::ShaLoad(0));
1295
1296 if self.sha_update() {
1297 (self.wakeup_device)();
1298
1299 self.send_command(COMMAND_OPCODE_SHA, SHA_UPDATE, 64, 64);
1300 }
1301 }
1302
1303 Ok(())
1304 }
1305
1306 fn clear_data(&self) {
1312 (self.wakeup_device)();
1313
1314 self.reset();
1315 }
1316}
1317
1318impl<'a> digest::DigestHash<'a, 32> for Atecc508a<'a> {
1319 fn set_hash_client(&'a self, _client: &'a dyn digest::ClientHash<32>) {
1320 unimplemented!()
1321 }
1322
1323 fn run(
1324 &'a self,
1325 digest: &'static mut [u8; 32],
1326 ) -> Result<(), (ErrorCode, &'static mut [u8; 32])> {
1327 let remain_len = self.remain_len.get();
1328
1329 if self.op.get() != Operation::ReadySha {
1330 return Err((ErrorCode::BUSY, digest));
1331 }
1332
1333 (self.wakeup_device)();
1334
1335 self.op.set(Operation::ShaRun(0));
1336 self.digest_data.replace(digest);
1337
1338 if remain_len > 0 {
1339 self.buffer.take().map(|buffer| {
1340 self.digest_buffer.map(|digest_buffer| {
1341 buffer[ATRCC508A_PROTOCOL_FIELD_DATA
1342 ..(ATRCC508A_PROTOCOL_FIELD_DATA + remain_len)]
1343 .copy_from_slice(&digest_buffer[0..remain_len]);
1344 });
1345
1346 self.buffer.replace(buffer);
1347 });
1348 }
1349
1350 self.send_command(
1351 COMMAND_OPCODE_SHA,
1352 SHA_END,
1353 self.remain_len.get() as u16,
1354 remain_len,
1355 );
1356
1357 Ok(())
1358 }
1359}
1360
1361impl<'a> digest::DigestDataHash<'a, 32> for Atecc508a<'a> {
1362 fn set_client(&'a self, client: &'a dyn digest::ClientDataHash<32>) {
1363 self.digest_client.set(client);
1364 }
1365}
1366
1367impl<'a> SignatureVerify<'a, 32, 64> for Atecc508a<'a> {
1368 fn set_verify_client(&self, client: &'a dyn ClientVerify<32, 64>) {
1369 self.secure_client.set(client);
1370 }
1371
1372 fn verify(
1378 &self,
1379 hash: &'static mut [u8; 32],
1380 signature: &'static mut [u8; 64],
1381 ) -> Result<(), (ErrorCode, &'static mut [u8; 32], &'static mut [u8; 64])> {
1382 if self.ext_public_key.is_none() {
1383 return Err((ErrorCode::OFF, hash, signature));
1384 }
1385
1386 (self.wakeup_device)();
1387
1388 self.op.set(Operation::LoadTempKeyNonce(0));
1389
1390 self.buffer.map(|buffer| {
1391 buffer[ATRCC508A_PROTOCOL_FIELD_DATA..(ATRCC508A_PROTOCOL_FIELD_DATA + 32)]
1392 .copy_from_slice(hash);
1393 });
1394
1395 self.message_data.replace(hash);
1396 self.signature_data.replace(signature);
1397
1398 self.send_command(COMMAND_OPCODE_NONCE, NONCE_MODE_PASSTHROUGH, 0x0000, 32);
1399
1400 Ok(())
1401 }
1402}
1403
1404impl<'a> keys::SetKeyBySlice<'a, 64> for Atecc508a<'a> {
1405 fn set_key(
1406 &self,
1407 key: &'static mut [u8; 64],
1408 ) -> Result<(), (ErrorCode, &'static mut [u8; 64])> {
1409 self.ext_public_key.map(|epkey| {
1411 epkey.copy_from_slice(key);
1412 });
1413
1414 self.ext_public_key_temp.replace(key);
1416 self.deferred_call.set();
1417 Ok(())
1418 }
1419
1420 fn set_client(&self, client: &'a dyn keys::SetKeyBySliceClient<64>) {
1421 self.key_set_client.replace(client);
1422 }
1423}
1424
1425impl kernel::deferred_call::DeferredCallClient for Atecc508a<'_> {
1426 fn handle_deferred_call(&self) {
1427 self.key_set_client.map(|client| {
1428 self.ext_public_key_temp
1429 .take()
1430 .map(|key| client.set_key_done(key, Ok(())))
1431 });
1432 }
1433
1434 fn register(&'static self) {
1435 self.deferred_call.register(self);
1436 }
1437}