Skip to content

Commit

Permalink
Merge pull request #840 from LedgerHQ/add-privacy-report-warning-use-…
Browse files Browse the repository at this point in the history
…case

Add privacy report warning in NBGL Use Case
  • Loading branch information
nroggeman-ledger authored Jan 24, 2025
2 parents 69fe88c + 12a53b2 commit 4988724
Show file tree
Hide file tree
Showing 14 changed files with 891 additions and 136 deletions.
168 changes: 168 additions & 0 deletions lib_nbgl/doc/nbgl_use_case.dox
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ A few APIs are available to draw typical Use-Cases, such as:
- @ref nbgl_useCaseReview() to draw the pages of a regular coin transaction review, when all info are available from the beginning (see @subpage use_case_review)
- @ref nbgl_useCaseReviewLight() to draw the pages of a transaction review with a simple button confirmation, when all info are available from the beginning (see @subpage use_case_review_light)
- @ref nbgl_useCaseReviewStreamingStart() to draw the pages of a regular coin transaction review, when all info are not available from the beginning (see @subpage use_case_review_streaming)
- for reviews with a warning prolog:
- @ref nbgl_useCaseReviewWithWarning() to draw the pages of a regular coin transaction review, when all info are available from the beginning, but with an identified risk requiring a warning prolog (see @subpage use_case_review_with_warning)
- @ref nbgl_useCaseReviewStreamingWithWarningStart() to draw the pages of a regular coin transaction review, when all info are not available from the beginning, but with an identified risk requiring a warning prolog (see @subpage use_case_review_with_warning and @subpage use_case_review_streaming)
- for address verification:
- @ref nbgl_useCaseAddressReview() to draw an address confirmation page, with a possibility to see it as QR Code and some extra tag/value pairs (see @subpage use_case_addr_review)
- for keypad:
Expand Down Expand Up @@ -455,6 +458,171 @@ void staticReview(void) {
}
@endcode

@subsection use_case_review_with_warning Review with warning Use Case

\image{inline} html UseCase-Review-With-Warning.png "caption" height=500

The review itself behaves like in @subpage use_case_review. The main differences are:

- The review itself is preceded by a warning page offering the possibility to cancel the review ("Back to safety") or to start it ("Continue anyway")
- In the first and last pages of the actual review, a top-right button offers the possibility to get more information about the warning

The API to initiate the display of the series of pages is @ref nbgl_useCaseReviewWithWarning(), providing:

- the type of operation to review (transaction, message or generic operation)
- the list of tag/value pairs (or a callback to get them one by one)
- the texts/icon to use in presentation page and in last page
- the configuration to use for the warning (see @ref nbgl_warning_t structure)
- a callback called when the long press button on last page or reject confirmation is used. The callback's param is *true* for confirmation, *false* for rejection.

@note the recommended configuration for warning is the predefined one. In this case, one just has to fill the *predefinedSet* field of @ref nbgl_warning_t with the appropriate warning
causes (bitfield) and the *reportProvider* field with the name of the 3rd party providing the Web3Checks report, if necessary.

Here is the code to display something similar to example picture:

@code
// 4 pairs of tag/value to display
static nbgl_layoutTagValue_t pairs[4];

static const nbgl_contentTagValueList_t pairList = {
.nbMaxLinesForValue = 0,
.nbPairs = 4,
.pairs = (nbgl_layoutTagValue_t*)pairs
};

// warning description (cannot be in call stack)
static nbgl_warning_t warningDesc;

// called when long press button on 3rd page is long-touched or when reject footer is touched
static void onReviewResult(bool confirm) {
// display a status page and go back to main
if (confirm) {
nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_SIGNED, appMain);
}
else {
nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_REJECTED, appMain);
}
}

void staticReview(void) {
warningDesc.predefinedSet = (1 << W3C_LOSING_SWAP_WARN) | (1 << BLIND_SIGNING_WARN);
warningDesc.reportProvider = "Blockaid";

// static review, providing the whole list of pairs
nbgl_useCaseReviewWithWarning(TYPE_TRANSACTION, // type of operation
&pairList, // list of tag/value pairs
coinIcon, // icon of the coin
"Review transaction\nto send coin", // title of the first page
NULL, // sub-title of the first page
"Sign transaction to\nsend coin?", // title of the last page
NULL, // no tip-box in first page of review
warningDesc, // description of warning causes
onReviewResult); // callback on result of the review
}
@endcode

Here is another version of the example code, not using predefined text:

@code
// 4 pairs of tag/value to display
static nbgl_layoutTagValue_t pairs[4];

static const nbgl_contentTagValueList_t pairList = {
.nbMaxLinesForValue = 0,
.nbPairs = 4,
.pairs = (nbgl_layoutTagValue_t*)pairs
};

// icons for first level warning details
static const nbgl_icon_details_t *barListIcons[] = {&WARNING_ICON, &INFO_I_ICON};

// first level warning details
static const char *const barListTexts[] = {"Blind signing", "Risk detected"};
static const char *const barListSubTexts[] = {"This transaction cannot be fully decoded.", "Web3 Checks found a risk:\nLosing swap"};
// second level warning details in prolog
static const struct nbgl_warningDetails_s barListIntroDetails[] = {
{.title = "Back",
.type = QRCODE_WARNING,
.qrCode = {.url = "ledger.com/e8", .text1 = "ledger.com/e8", .text2 = "Scan to learn about the risks of blind signing.", .centered = true}},
{.title = "Back",
.type = QRCODE_WARNING,
.qrCode = {.url = "url.com/od24xz", .text1 = "url.com/od24xz", .text2 = "Scan to view the risk report from Blockaid.", .centered = true}}
};

// second level warning details in review
static const struct nbgl_warningDetails_s barListIntroDetails[] = {
{.title = "Back",
.type = CENTERED_INFO_WARNING,
.centeredInfo = {.icon = &C_Warning_64px, .title = "Blind signing", .description = "This transaction’s details are not fully verifiable. If you sign it, you could lose all your assets.\n\nLearn about blind signing:
ledger.com/e8"}},
{.title = "Back",
.type = CENTERED_INFO_WARNING,
.centeredInfo = {.icon = &C_Warning_64px, .title = "Risk detected", .description = "This transaction was scanned as risky by Web3 Checks.\n\nView full Blockaid report:url.com/od24xz"}}
};

// info in main warning page
static const nbgl_contentCenter_t warningInfo = {
.icon = &C_Warning_64px,
.title = "Dangerous transaction",
.description = "This transaction cannot be fully decoded, and was marked risky by Web3 Checks."
};

// first level warning details in prolog
static const nbgl_warningDetails_t warningIntroDetails = {
.title = "Security report",
.type = BAR_LIST_WARNING,
.barList.nbBars = 2,
.barList.icons = barListIcons,
.texts = barListTexts,
.subTexts = barListSubTexts,
.barList.details = barListIntroDetails
};

// first level warning details in review (when pressing top-right from first and last pages)
static const nbgl_warningDetails_t warningReviewDetails = {
.title = "Security report",
.type = BAR_LIST_WARNING,
.barList.nbBars = 2,
.barList.icons = barListIcons,
.texts = barListTexts,
.subTexts = barListSubTexts,
.barList.details = barListReviewDetails
};

// warning description (cannot be in call stack)
static const nbgl_warning_t warningDesc = {
.info = &warningInfo,
.introTopRightIcon = &PRIVACY_ICON,
.reviewTopRightIcon = &WARNING_ICON,
.introDetails = &warningIntroDetails,
.reviewDetails = &warningReviewDetails
};

// called when long press button on 3rd page is long-touched or when reject footer is touched
static void onReviewResult(bool confirm) {
// display a status page and go back to main
if (confirm) {
nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_SIGNED, appMain);
}
else {
nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_REJECTED, appMain);
}
}

void staticReview(void) {
// static review, providing the whole list of pairs
nbgl_useCaseReviewWithWarning(TYPE_TRANSACTION, // type of operation
&pairList, // list of tag/value pairs
coinIcon, // icon of the coin
"Review transaction\nto send coin", // title of the first page
NULL, // sub-title of the first page
"Sign transaction to\nsend coin?", // title of the last page
NULL, // no tip-box in first page of review
warningDesc, // description of warning causes
onReviewResult); // callback on result of the review
}
@endcode

@subsection use_case_addr_review Address Review Use Case

\image{inline} html UseCase-AddressReview.png "caption" height=500
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lib_nbgl/glyphs/32px/Exclamation_32px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lib_nbgl/glyphs/32px/Privacy_32px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lib_nbgl/glyphs/40px/Exclamation_40px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lib_nbgl/glyphs/40px/Important_Circle_40px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added lib_nbgl/glyphs/40px/Privacy_40px.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions lib_nbgl/include/nbgl_obj.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ extern "C" {
#define QRCODE_ICON C_QRCode_32px
#define MINI_PUSH_ICON C_Mini_Push_32px
#define WARNING_ICON C_Warning_32px
#define ROUND_WARN_ICON C_Important_Circle_32px
#define PRIVACY_ICON C_Privacy_32px
#define EXCLAMATION_ICON C_Exclamation_32px
#else // TARGET_STAX
#define SPACE_ICON C_Space_40px
#define BACKSPACE_ICON C_Erase_40px
Expand All @@ -146,6 +149,9 @@ extern "C" {
#define QRCODE_ICON C_QRCode_40px
#define MINI_PUSH_ICON C_Mini_Push_40px
#define WARNING_ICON C_Warning_40px
#define ROUND_WARN_ICON C_Important_Circle_40px
#define PRIVACY_ICON C_Privacy_40px
#define EXCLAMATION_ICON C_Exclamation_40px
#endif // TARGET_STAX

// For backward compatibility, to be remove later
Expand Down
1 change: 1 addition & 0 deletions lib_nbgl/include/nbgl_step.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ typedef void (*nbgl_stepMenuListCallback_t)(uint8_t choiceIndex);

/**
* @brief prototype of function to be called when buttons are touched on a screen
* @param stepCtx context returned by the nbgl_stepDrawXXX function
* @param event type of button event
*/
typedef void (*nbgl_stepButtonCallback_t)(nbgl_step_t stepCtx, nbgl_buttonEvent_t event);
Expand Down
104 changes: 100 additions & 4 deletions lib_nbgl/include/nbgl_use_case.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ typedef void (*nbgl_actionCallback_t)(uint8_t page);

/**
* @brief prototype of pin validation callback function
* @param content pin value
* @param length pin length
* @param pin pin value
* @param pinLen pin length
*/
typedef void (*nbgl_pinValidCallback_t)(const uint8_t *content, uint8_t page);
typedef void (*nbgl_pinValidCallback_t)(const uint8_t *pin, uint8_t pinLen);

/**
* @brief prototype of content navigation callback function
Expand Down Expand Up @@ -188,6 +188,87 @@ typedef struct {
};
} nbgl_tipBox_t;

/**
* @brief The different types of warning page contents
*
*/
typedef enum {
CENTERED_INFO_WARNING = 0, ///< Centered info
QRCODE_WARNING, ///< QR Code
BAR_LIST_WARNING ///< list of touchable bars, to display sub-pages
} nbgl_warningDetailsType_t;

/**
* @brief The necessary parameters to build a list of touchable bars, to display sub-pages
*
*/
typedef struct {
uint8_t nbBars; ///< number of touchable bars
const char *const *texts; ///< array of texts for each bar (nbBars items, in black/bold)
const char *const *subTexts; ///< array of texts for each bar (nbBars items, in black)
const nbgl_icon_details_t **icons; ///< array of icons for each bar (nbBars items)
const struct nbgl_warningDetails_s
*details; ///< array of nbBars structures giving what to display when each bar is touched.
} nbgl_warningBarList_t;

/**
* @brief The necessary parameters to build the page(s) displayed when the top-right button is
* touched in intro page (before review)
*
*/
typedef struct nbgl_warningDetails_s {
const char *title; ///< text of the page (used to go back)
nbgl_warningDetailsType_t
type; ///< type of content in the page, determining what to use in the following union
union {
nbgl_contentCenter_t
centeredInfo; ///< centered info, if type == @ref CENTERED_INFO_WARNING
#ifdef NBGL_QRCODE
nbgl_layoutQRCode_t qrCode; ///< QR code, if type == @ref QRCODE_WARNING
#endif // NBGL_QRCODE
nbgl_warningBarList_t barList; ///< touchable bars list, if type == @ref BAR_LIST_WARNING
};
} nbgl_warningDetails_t;

/**
* @brief The different types of pre-defined warnings
*
*/
typedef enum {
BLIND_SIGNING_WARN = 0, ///< Blind signing
W3C_ISSUE_WARN, ///< Web3 Checks issue
W3C_LOSING_SWAP_WARN, ///< Web3 Checks: Losing Swap risk
W3C_THREAT_DETECTED_WARN, ///< Web3 Checks: Thread detexted, malicious (know drainer)
NB_WARNING_TYPES
} nbgl_warningType_t;

/**
* @brief The necessary parameters to build a warning page preceding a review.
* One can either use `predefinedSet` when the warnings are already supported in @ref
* nbgl_warningType_t list, or use `introDetails` or `reviewDetails` to configure manually the
* warning pages
* @note it's also used to build the modal pages displayed when touching the top-right button in the
* review's first page
*
*/
typedef struct {
uint32_t predefinedSet; ///< bitfield of pre-defined warnings, to be taken in @ref
///< nbgl_warningType_t set it to 0 if not using pre-defined warnings
const char *reportProvider; ///< name of the security report provider, used in some strings
const nbgl_warningDetails_t
*introDetails; ///< details displayed when top-right button is touched in intro page
///< (before review) if using pre-defined configuration, set to NULL,
const nbgl_warningDetails_t
*reviewDetails; ///< details displayed when top-right button is touched in first/last page
///< of review if using pre-defined configuration, set to NULL
const nbgl_contentCenter_t
*info; ///< parameters to build the intro warning page, if not using pre-defined
const nbgl_icon_details_t
*introTopRightIcon; ///< icon to use in the intro warning page, if not using pre-defined
const nbgl_icon_details_t *reviewTopRightIcon; ///< icon to use in the first/last page of
///< review, if not using pre-defined
} nbgl_warning_t;

/**
* @brief The different types of operation to review
*
Expand Down Expand Up @@ -265,7 +346,15 @@ void nbgl_useCaseReviewBlindSigning(nbgl_operationType_t operationT
const char *finishTitle,
const nbgl_tipBox_t *tipBox,
nbgl_choiceCallback_t choiceCallback);

void nbgl_useCaseReviewWithWarning(nbgl_operationType_t operationType,
const nbgl_contentTagValueList_t *tagValueList,
const nbgl_icon_details_t *icon,
const char *reviewTitle,
const char *reviewSubTitle,
const char *finishTitle,
const nbgl_tipBox_t *tipBox,
const nbgl_warning_t *warning,
nbgl_choiceCallback_t choiceCallback);
void nbgl_useCaseAdvancedReview(nbgl_operationType_t operationType,
const nbgl_contentTagValueList_t *tagValueList,
const nbgl_icon_details_t *icon,
Expand Down Expand Up @@ -305,6 +394,13 @@ void nbgl_useCaseReviewStreamingBlindSigningStart(nbgl_operationType_t ope
const char *reviewSubTitle,
nbgl_choiceCallback_t choiceCallback);

void nbgl_useCaseReviewStreamingWithWarningStart(nbgl_operationType_t operationType,
const nbgl_icon_details_t *icon,
const char *reviewTitle,
const char *reviewSubTitle,
const nbgl_warning_t *warning,
nbgl_choiceCallback_t choiceCallback);

void nbgl_useCaseReviewStreamingContinueExt(const nbgl_contentTagValueList_t *tagValueList,
nbgl_choiceCallback_t choiceCallback,
nbgl_callback_t skipCallback);
Expand Down
Loading

0 comments on commit 4988724

Please sign in to comment.