blob: f31fa5287049ce487b15309a79c9c969b6413417 [file] [log] [blame]
developer02e65912023-08-17 16:33:10 +08001/* api_global_eip74.c
2 *
3 * Deterministic Random Bit Generator (EIP-74) Global Control Initialization
4 * Adapter. The EIP-74 is used to generate pseudo-random IVs for outbound
5 * operations in CBC mode.
6 */
7
8/*****************************************************************************
9* Copyright (c) 2017-2020 by Rambus, Inc. and/or its subsidiaries.
10*
11* This program is free software: you can redistribute it and/or modify
12* it under the terms of the GNU General Public License as published by
13* the Free Software Foundation, either version 2 of the License, or
14* any later version.
15*
16* This program is distributed in the hope that it will be useful,
17* but WITHOUT ANY WARRANTY; without even the implied warranty of
18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19* GNU General Public License for more details.
20*
21* You should have received a copy of the GNU General Public License
22* along with this program. If not, see <http://www.gnu.org/licenses/>.
23*****************************************************************************/
24
25/*----------------------------------------------------------------------------
26 * This module implements (provides) the following interface(s):
27 */
28#include "api_global_eip74.h"
29
30
31/*----------------------------------------------------------------------------
32 * This module uses (requires) the following interface(s):
33 */
34
35// Configuration.
36#include "c_adapter_eip74.h"
37
38// Driver Framework Basic Definitions API
39#include "basic_defs.h" // bool, uint8_t
40
41// memcpy
42#include "clib.h"
43
44// EIP-73 Driver Library.
45#include "eip74.h"
46
47#include "device_types.h" // Device_Handle_t
48#include "device_mgmt.h" // Device_find
49
50// Logging API
51#include "log.h" // Log_*, LOG_*
52
53// Adapter interrupts API
54#include "adapter_interrupts.h" // Adapter_Interrupt_*
55
56// Runtime Power Management Device Macros API
57#include "rpm_device_macros.h" // RPM_*
58
59
60/*----------------------------------------------------------------------------
61 * Definitions and macros
62 */
63
64
65/*----------------------------------------------------------------------------
66 * Local variables
67 */
68
69/* Put all adapter local variables in one structure */
70static struct {
71 EIP74_IOArea_t IOArea;
72#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
73 GlobalControl74_NotifyFunction_t Notify_CBFunc;
74#endif
75#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
76 GlobalControl74_Configuration_t CachedConfig;
77 bool fInitialized;
78#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
79 bool fInterruptEnabled;
80#endif
81#endif
82} EIP74State;
83
84
85static const GlobalControl74_Capabilities_t Global_CapabilitiesString =
86{
87 "EIP-74 v_._p_"// szTextDescription
88};
89
90
91/*----------------------------------------------------------------------------
92 * GlobalControl74Lib_Init
93 */
94static GlobalControl74_Error_t
95GlobalControl74Lib_Init(
96 const GlobalControl74_Configuration_t * const Configuration_p,
97 const uint8_t * const Entropy_p);
98
99
100#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
101/*----------------------------------------------------------------------------
102 * GlobalControl74Lib_Resune
103 */
104static int
105GlobalControl74Lib_Resune(
106 void *p)
107{
108 uint8_t Entropy[48];
109 IDENTIFIER_NOT_USED(p);
110 if (EIP74State.fInitialized)
111 {
112 /* Note we should add fresh random data here */
113 ZEROINIT(Entropy);
114 if (GlobalControl74Lib_Init(&EIP74State.CachedConfig, Entropy) !=
115 GLOBAL_CONTROL_EIP74_NO_ERROR)
116 {
117 return -1;
118 }
119
120#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
121 if (EIP74State.fInitialized && EIP74State.fInterruptEnabled)
122 {
123 Adapter_Interrupt_Disable(ADAPTER_EIP74_ERR_IRQ, 0);
124 Adapter_Interrupt_Disable(ADAPTER_EIP74_RES_IRQ, 0);
125 }
126#endif
127 }
128 return 0;
129}
130
131
132/*----------------------------------------------------------------------------
133 * GlobalControl74Lib_Suspend
134 */
135static int
136GlobalControl74Lib_Suspend(
137 void *p)
138{
139 IDENTIFIER_NOT_USED(p);
140#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
141 if (EIP74State.fInitialized && EIP74State.fInterruptEnabled)
142 {
143 Adapter_Interrupt_Disable(ADAPTER_EIP74_ERR_IRQ, 0);
144 Adapter_Interrupt_Disable(ADAPTER_EIP74_RES_IRQ, 0);
145 }
146#endif
147 return 0;
148}
149
150#endif
151
152/*----------------------------------------------------------------------------
153 * GlobalControl74Lib_CopyKeyMat
154 *
155 * Copy a key represented as a byte array into a word array..
156 *
157 * Destination_p (input)
158 * Destination (word-aligned) of the word array
159 *
160 * Source_p (input)
161 * Source (byte aligned) of the data.
162 *
163 * KeyByteCount (input)
164 * Size of the key in bytes.
165 *
166 * Destination_p is allowed to be a null pointer, in which case no key
167 * will be written.
168 */
169static void
170GlobalControl74Lib_CopyKeyMat(
171 uint32_t * const Destination_p,
172 const uint8_t * const Source_p,
173 const unsigned int KeyByteCount)
174{
175 uint32_t *dst = Destination_p;
176 const uint8_t *src = Source_p;
177 unsigned int i,j;
178 uint32_t w;
179 if (Destination_p == NULL)
180 return;
181 for(i=0; i < KeyByteCount / sizeof(uint32_t); i++)
182 {
183 w=0;
184 for(j=0; j<sizeof(uint32_t); j++)
185 w=(w<<8)|(*src++);
186 *dst++ = w;
187 }
188}
189
190#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
191/*----------------------------------------------------------------------------
192 * GlobalControl74_InterruptHandlerNotify
193 */
194static void
195GlobalControl74_InterruptHandlerNotify(
196 const int nIRQ,
197 const unsigned int flags)
198{
199 GlobalControl74_NotifyFunction_t CB_Func = EIP74State.Notify_CBFunc;
200
201 IDENTIFIER_NOT_USED(nIRQ);
202 IDENTIFIER_NOT_USED(flags);
203
204 LOG_INFO("GlobalControl74_InterruptHandlerNotify\n");
205#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
206 EIP74State.fInterruptEnabled = true;
207#endif
208
209 EIP74State.Notify_CBFunc = NULL;
210 if (CB_Func != NULL)
211 {
212 LOG_INFO("\t Invoking callback\n");
213 CB_Func();
214 }
215}
216#endif
217/*----------------------------------------------------------------------------
218 * GlobalControl74Lib_Init
219 *
220 * This function performs the initialization of the EIP-74 Deterministic
221 * Random Bit Generator.
222 *
223 * Note: the Device was already found and the IOArea is already initialized.
224 *
225 * Configuration_p (input)
226 * Configuration parameters of the DRBG.
227 *
228 * Entropy_p (input)
229 * Pointer to a string of exactly 48 bytes that serves as the entropy.
230 * to initialize the DRBG.
231 *
232 * Return value
233 * GLOBAL_CONTROL_EIP74_NO_ERROR : initialization performed successfully
234 * GLOBAL_CONTROL_EIP74_ERROR_INTERNAL : initialization failed
235 */
236static GlobalControl74_Error_t
237GlobalControl74Lib_Init(
238 const GlobalControl74_Configuration_t * const Configuration_p,
239 const uint8_t * const Entropy_p)
240{
241 EIP74_Error_t Rc;
242 EIP74_Configuration_t Conf;
243 unsigned LoopCounter = ADAPTER_EIP74_RESET_MAX_RETRIES;
244 uint32_t Entropy[12];
245
246 Rc = EIP74_Reset(&EIP74State.IOArea);
247 do
248 {
249 if (Rc == EIP74_BUSY_RETRY_LATER)
250 {
251 LoopCounter--;
252 if (LoopCounter == 0)
253 {
254 LOG_CRIT("%s EIP74 reset timed out\n",__func__);
255 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
256 }
257 Rc = EIP74_Reset_IsDone(&EIP74State.IOArea);
258 }
259 else if (Rc != EIP74_NO_ERROR)
260 {
261 LOG_CRIT("%s EIP74 reset error\n",__func__);
262 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
263 }
264 } while (Rc != EIP74_NO_ERROR);
265
266 if (Configuration_p->GenerateBlockSize == 0)
267 {
268 Conf.GenerateBlockSize = ADAPTER_EIP74_GEN_BLK_SIZE;
269 }
270 else
271 {
272 Conf.GenerateBlockSize = Configuration_p->GenerateBlockSize;
273 }
274
275 if (Configuration_p->ReseedThr == 0)
276 {
277 Conf.ReseedThr = ADAPTER_EIP74_RESEED_THR;
278 }
279 else
280 {
281 Conf.ReseedThr = Configuration_p->ReseedThr;
282 }
283
284 if (Configuration_p->ReseedThrEarly == 0)
285 {
286 Conf.ReseedThrEarly = ADAPTER_EIP74_RESEED_THR_EARLY;
287 }
288 else
289 {
290 Conf.ReseedThrEarly = Configuration_p->ReseedThrEarly;
291 }
292
293 Rc = EIP74_Configure(&EIP74State.IOArea, &Conf);
294 if (Rc != EIP74_NO_ERROR)
295 {
296 LOG_CRIT("%s EIP74 could not be configured\n",__func__);
297 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
298 }
299
300 GlobalControl74Lib_CopyKeyMat(Entropy, Entropy_p, 48);
301
302 Rc = EIP74_Instantiate(&EIP74State.IOArea, Entropy, Configuration_p->fStuckOut);
303
304 if (Rc != EIP74_NO_ERROR)
305 {
306 LOG_CRIT("%s EIP74 could not be instantiated\n",__func__);
307 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
308 }
309
310 return GLOBAL_CONTROL_EIP74_NO_ERROR;
311}
312
313
314/*----------------------------------------------------------------------------
315 * GlobalControl74_Capabilities_Get
316 */
317void
318GlobalControl74_Capabilities_Get(
319 GlobalControl74_Capabilities_t * const Capabilities_p)
320{
321 Device_Handle_t Device;
322 uint8_t Versions[3];
323 LOG_INFO("\n\t\t\t GlobalControl74_Capabilities_Get\n");
324
325 memcpy(Capabilities_p, &Global_CapabilitiesString,
326 sizeof(Global_CapabilitiesString));
327
328 Device = Device_Find(ADAPTER_EIP74_DEVICE_NAME);
329 if (Device == NULL)
330 {
331 LOG_CRIT("%s EIP74 Device not found\n",__func__);
332 return;
333 }
334
335 {
336 EIP74_Capabilities_t Capabilities;
337 EIP74_Error_t Rc;
338
339 if (RPM_DEVICE_IO_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
340 RPM_FLAG_SYNC) != RPM_SUCCESS)
341 return;
342
343 Rc = EIP74_HWRevision_Get(Device, &Capabilities);
344
345 (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
346 RPM_FLAG_ASYNC);
347
348 if (Rc != EIP74_NO_ERROR)
349 {
350 LOG_CRIT("%s EIP74_Capaboilities_Get() failed\n",__func__);
351 return;
352 }
353
354 Log_FormattedMessage(
355 "EIP74 options: Nof Clients=%u Nof AESCores=%u\n"
356 "\t\tAESSpeed=%u FIFODepth=%u\n",
357 Capabilities.HW_Options.ClientCount,
358 Capabilities.HW_Options.AESCoreCount,
359 Capabilities.HW_Options.AESSpeed,
360 Capabilities.HW_Options.FIFODepth);
361
362
363 Versions[0] = Capabilities.HW_Revision.MajHWRevision;
364 Versions[1] = Capabilities.HW_Revision.MinHWRevision;
365 Versions[2] = Capabilities.HW_Revision.HWPatchLevel;
366 }
367
368 {
369 char * p = Capabilities_p->szTextDescription;
370 int VerIndex = 0;
371 int i = 0;
372
373 while(p[i])
374 {
375 if (p[i] == '_' && VerIndex < 3)
376 {
377 if (Versions[VerIndex] > 9)
378 p[i] = '?';
379 else
380 p[i] = '0' + Versions[VerIndex];
381
382 VerIndex++;
383 }
384
385 i++;
386 }
387 }
388}
389
390
391/*----------------------------------------------------------------------------
392 * GlobalControl74_Init
393 */
394GlobalControl74_Error_t
395GlobalControl74_Init(
396 const GlobalControl74_Configuration_t * const Configuration_p,
397 const uint8_t * const Entropy_p)
398{
399 EIP74_Error_t Rc;
400 Device_Handle_t Device;
401
402 LOG_INFO("\n\t\t\t GlobalControl74_Init\n");
403
404 Device = Device_Find(ADAPTER_EIP74_DEVICE_NAME);
405 if (Device == NULL)
406 {
407 LOG_CRIT("%s EIP74 Device not found\n",__func__);
408 return GLOBAL_CONTROL_EIP74_ERROR_NOT_IMPLEMENTED;
409 }
410
411
412 Rc = EIP74_Init(&EIP74State.IOArea, Device);
413 if (Rc != EIP74_NO_ERROR)
414 {
415 LOG_CRIT("%s EIP74 could not be initialized\n",__func__);
416 return GLOBAL_CONTROL_EIP74_ERROR_NOT_IMPLEMENTED;
417 }
418
419 if (RPM_DEVICE_INIT_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
420 GlobalControl74Lib_Suspend,
421 GlobalControl74Lib_Resume) != RPM_SUCCESS)
422 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
423
424 if (GlobalControl74Lib_Init(Configuration_p,Entropy_p) !=
425 GLOBAL_CONTROL_EIP74_NO_ERROR)
426 {
427 (void)RPM_DEVICE_INIT_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID);
428
429 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
430 }
431
432
433#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
434 EIP74State.fInitialized = true;
435 EIP74State.CachedConfig = *Configuration_p;
436#endif
437 (void)RPM_DEVICE_INIT_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID);
438
439
440#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
441 Adapter_Interrupt_SetHandler(ADAPTER_EIP74_ERR_IRQ,
442 GlobalControl74_InterruptHandlerNotify);
443 Adapter_Interrupt_SetHandler(ADAPTER_EIP74_RES_IRQ,
444 GlobalControl74_InterruptHandlerNotify);
445#endif
446
447 return GLOBAL_CONTROL_EIP74_NO_ERROR;
448}
449
450
451
452/*----------------------------------------------------------------------------
453 * GlobalControl74_UnInit
454 */
455GlobalControl74_Error_t
456GlobalControl74_UnInit(void)
457{
458 EIP74_Error_t Rc;
459 unsigned LoopCounter = ADAPTER_EIP74_RESET_MAX_RETRIES;
460
461 LOG_INFO("\n\t\t\t GlobalControl74_UnInit\n");
462
463#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
464 Adapter_Interrupt_SetHandler(ADAPTER_EIP74_ERR_IRQ, NULL);
465 Adapter_Interrupt_SetHandler(ADAPTER_EIP74_RES_IRQ, NULL);
466 Adapter_Interrupt_Disable(ADAPTER_EIP74_ERR_IRQ, 0);
467 Adapter_Interrupt_Disable(ADAPTER_EIP74_RES_IRQ, 0);
468#endif
469 (void)RPM_DEVICE_UNINIT_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID, false);
470
471 Rc = EIP74_Reset(&EIP74State.IOArea);
472 do
473 {
474 if (Rc == EIP74_BUSY_RETRY_LATER)
475 {
476 LoopCounter--;
477 if (LoopCounter == 0)
478 {
479 LOG_CRIT("%s EIP74 reset timed out\n",__func__);
480 (void)RPM_DEVICE_UNINIT_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID);
481 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
482 }
483 Rc = EIP74_Reset_IsDone(&EIP74State.IOArea);
484 }
485 else if (Rc != EIP74_NO_ERROR)
486 {
487 LOG_CRIT("%s EIP74 reset error\n",__func__);
488 (void)RPM_DEVICE_UNINIT_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID);
489
490 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
491 }
492 } while (Rc != EIP74_NO_ERROR);
493 (void)RPM_DEVICE_UNINIT_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID);
494
495#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
496 EIP74State.fInitialized = false;
497#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
498 EIP74State.fInterruptEnabled = false;
499#endif
500#endif
501
502 return GLOBAL_CONTROL_EIP74_NO_ERROR;
503}
504
505
506/*----------------------------------------------------------------------------
507 * GlobalControl74_Reseed
508 */
509GlobalControl74_Error_t
510GlobalControl74_Reseed(
511 const uint8_t * const Entropy_p)
512{
513 EIP74_Error_t Rc;
514 uint32_t Entropy[12];
515 LOG_INFO("\n\t\t\t GlobalControl74_Reseed\n");
516
517
518 GlobalControl74Lib_CopyKeyMat(Entropy, Entropy_p, 48);
519
520 if (RPM_DEVICE_IO_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
521 RPM_FLAG_SYNC) != RPM_SUCCESS)
522 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
523
524 Rc = EIP74_Reseed(&EIP74State.IOArea, Entropy);
525
526 (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
527 RPM_FLAG_ASYNC);
528
529 if (Rc != EIP74_NO_ERROR)
530 {
531 LOG_CRIT("%s EIP74 could not be reseeded\n",__func__);
532 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
533 }
534
535 return GLOBAL_CONTROL_EIP74_NO_ERROR;
536}
537
538
539/*----------------------------------------------------------------------------
540 * GlobalControl74_Status_Get
541 */
542GlobalControl74_Error_t
543GlobalControl74_Status_Get(
544 GlobalControl74_Status_t * const Status_p)
545{
546 EIP74_Error_t Rc;
547 EIP74_Status_t Status;
548 LOG_INFO("\n\t\t\t GlobalControl74_Status_Get\n");
549
550 if (RPM_DEVICE_IO_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
551 RPM_FLAG_SYNC) != RPM_SUCCESS)
552 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
553
554 Rc = EIP74_Status_Get(&EIP74State.IOArea, &Status);
555
556 (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
557 RPM_FLAG_ASYNC);
558
559 if (Rc != EIP74_NO_ERROR)
560 {
561 LOG_CRIT("%s EIP74 status could not be read\n",__func__);
562 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
563 }
564
565 Status_p->GenerateBlockCount = Status.GenerateBlockCount;
566 Status_p->fStuckOut = Status.fStuckOut;
567 Status_p->fNotInitialized = Status.fNotInitialized;
568 Status_p->fReseedError = Status.fReseedError;
569 Status_p->fReseedWarning = Status.fReseedWarning;
570 Status_p->fInstantiated = Status.fInstantiated;
571 Status_p->AvailableCount = Status.AvailableCount;
572
573 return GLOBAL_CONTROL_EIP74_NO_ERROR;
574}
575
576/*----------------------------------------------------------------------------
577 * GlobalControl74_Clear
578 */
579GlobalControl74_Error_t
580GlobalControl74_Clear(void)
581{
582 EIP74_Error_t Rc;
583 LOG_INFO("\n\t\t\t GlobalControl74_Clear\n");
584
585 if (RPM_DEVICE_IO_START_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
586 RPM_FLAG_SYNC) != RPM_SUCCESS)
587 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
588
589 Rc = EIP74_Clear(&EIP74State.IOArea);
590
591 (void)RPM_DEVICE_IO_STOP_MACRO(ADAPTER_GLOBAL_RPM_EIP74_DEVICE_ID,
592 RPM_FLAG_ASYNC);
593
594 if (Rc != EIP74_NO_ERROR)
595 {
596 LOG_CRIT("%s EIP74 could not be cleared\n",__func__);
597 return GLOBAL_CONTROL_EIP74_ERROR_INTERNAL;
598 }
599
600 return GLOBAL_CONTROL_EIP74_NO_ERROR;
601}
602
603
604#ifdef ADAPTER_EIP74_INTERRUPTS_ENABLE
605/*----------------------------------------------------------------------------
606 * GlobalControl74_Notify_Request
607 */
608GlobalControl74_Error_t
609GlobalControl74_Notify_Request(
610 GlobalControl74_NotifyFunction_t CBFunc_p)
611{
612 LOG_INFO("\n\t\t\t GlobalControl74_Notify_Request\n");
613 IDENTIFIER_NOT_USED(CBFunc_p);
614
615 EIP74State.Notify_CBFunc = CBFunc_p;
616 if (CBFunc_p != NULL)
617 {
618 Adapter_Interrupt_Enable(ADAPTER_EIP74_ERR_IRQ, 0);
619 Adapter_Interrupt_Enable(ADAPTER_EIP74_RES_IRQ, 0);
620#ifdef ADAPTER_PEC_RPM_EIP74_DEVICE0_ID
621 EIP74State.fInterruptEnabled = true;
622#endif
623 }
624
625 return GLOBAL_CONTROL_EIP74_NO_ERROR;
626}
627#endif
628
629
630/* end of file adapter_global_eip74.c */