Example #1
0
/*! \fn     guiCardUnlockingProcess(void)
*   \brief  Function called for the user to unlock his smartcard
*   \return success status
*/
RET_TYPE guiCardUnlockingProcess(void)
{
    volatile uint16_t temp_pin;
    RET_TYPE temp_rettype;
    
    while (1)
    {
        if (guiGetPinFromUser(&temp_pin, ID_STRING_INSERT_PIN) == RETURN_OK)
        {            
            // Try unlocking the smartcard
            temp_rettype = mooltipassDetectedRoutine(&temp_pin);
            
            switch(temp_rettype)
            {
                case RETURN_MOOLTIPASS_4_TRIES_LEFT :
                {
                    // Smartcard unlocked
                    temp_pin = 0x0000;
                    return RETURN_OK;
                }
                case RETURN_MOOLTIPASS_0_TRIES_LEFT :
                {
                    guiDisplayInformationOnScreenAndWait(ID_STRING_CARD_BLOCKED);
                    return RETURN_NOK;
                }
                case RETURN_MOOLTIPASS_PB :
                {
                    guiDisplayInformationOnScreenAndWait(ID_STRING_PB_CARD);
                    return RETURN_NOK;
                }
                default :
                {
                    // Both the enum and the defines allow us to do that
                    guiDisplayInformationOnScreenAndWait(ID_STRING_WRONGPIN1LEFT + temp_rettype - RETURN_MOOLTIPASS_1_TRIES_LEFT);
                    break;
                }
            }
        }
        else
        {
            // User cancelled the request
            return RETURN_NOK;
        }
    }
}
/*! \fn     favoriteSelectionScreen(pNode* p, cNode* c)
*   \brief  Screen displayed to let the user choose a favorite
*   \param  p                   Pointer to a parent node
*   \param  c                   Pointer to a child node
*   \return Valid child node address or 0 otherwise
*/
uint16_t favoriteSelectionScreen(pNode* p, cNode* c)
{
    uint16_t picked_child = NODE_ADDR_NULL;
    uint16_t parentAddresses[USER_MAX_FAV];
    uint16_t childAddresses[USER_MAX_FAV];
    uint16_t tempparaddr, tempchildaddr;
    uint8_t action_chosen = FALSE;
    uint8_t nbFavorites = 0;
    uint8_t offset = 0;
    uint8_t led_mask;
    int8_t i, j;
    
    // Browse through the favorites
    for (i = 0; i < USER_MAX_FAV; i++)
    {
        // Read favorite, check that it is valid
        readFav(i, &tempparaddr, &tempchildaddr);
        
        // If so, store it in our know addresses
        if (tempparaddr != NODE_ADDR_NULL)
        {
            parentAddresses[nbFavorites] = tempparaddr;
            childAddresses[nbFavorites++] = tempchildaddr;
        }
    }    
    
    // If no favorite, return
    if (nbFavorites == 0)
    {
        guiDisplayInformationOnScreenAndWait(ID_STRING_NOSTOREDFAV);
        return NODE_ADDR_NULL;
    }
    
    // Loop until the user chooses smth
    while (action_chosen != TRUE)
    {
        // Draw asking bitmap
        oledBitmapDrawFlash(0, 0, BITMAP_LOGIN, 0);
        
        // Clear led_mask
        led_mask = 0;
        i = 0;
        
        // List logins on screen
        while (((offset + i) < nbFavorites) && (i != 4))
        {
            // Read child node to get login
            readChildNode(c, childAddresses[offset+i]);
            readParentNode(p, parentAddresses[offset+i]);
            
            // Print service / login on screen
            displayCredentialAtSlot(i+((i&0x02)<<2), (char*)c->login, INDEX_TRUNCATE_LOGIN_FAV);
            displayCredentialAtSlot(i+((~i&0x02)<<2), (char*)p->service, INDEX_TRUNCATE_LOGIN_FAV);
            
            // Increment i
            i++;
        }
        
        // If nothing after, hide right arrow
        if ((i != 4) || ((offset+i) == nbFavorites))
        {
            oledFillXY(177, 25, 16, 14, 0x00);
            led_mask |= LED_MASK_RIGHT;
        }
        
        // Light only the available choices
        for (j = i; j < 4; j++)
        {
            led_mask |= (1 << j);
        }
        
        // Display picture
        oledDisplayOtherBuffer();
        
        // Get touched quarter
        j = getTouchedPositionAnswer(led_mask);
        
        // Check its validity, knowing that by default we will return NODE_ADDR_NULL
        if (j == -1)
        {
            action_chosen = TRUE;
            // Time out
        }
        else if (j < i)
        {
            // Valid choice, load parent node as it will be used later
            readParentNode(p, parentAddresses[offset+j]);
            picked_child = childAddresses[offset+j];
            action_chosen = TRUE;
        }
        else if (j == TOUCHPOS_LEFT)
        {
            if (offset > 0)
            {
                offset -= 4;
            } 
            else
            {
                // User wants to go back
                action_chosen = TRUE;                
            }
        }
        else if ((j == TOUCHPOS_RIGHT) && (i == 4) && ((offset+i) != nbFavorites))
        {
            // If there are more nodes to display
            offset += 4;
        }
    }
    
    // Return selected child
    return picked_child;
}
/*! \fn     guiAskForLoginSelect(pNode* p, cNode* c, uint16_t parentNodeAddress)
*   \brief  Ask for user login selection / approval
*   \param  p                   Pointer to a parent node
*   \param  c                   Pointer to a child node
*   \param  parentNodeAddress   Address of the parent node
*   \param  bypass_confirmation Bool to bypass authorisation request
*   \return Valid child node address or 0 otherwise
*/
uint16_t guiAskForLoginSelect(pNode* p, cNode* c, uint16_t parentNodeAddress, uint8_t bypass_confirmation)
{
    uint16_t first_child_address, temp_child_address;
    uint16_t picked_child = NODE_ADDR_NULL;
    uint16_t addresses[4];
    uint8_t led_mask;
    int8_t i, j;
    
    // Check parent node address
    if (parentNodeAddress == NODE_ADDR_NULL)
    {
        return NODE_ADDR_NULL;
    }
    
    // Read the parent node
    readParentNode(p, parentNodeAddress);
    
    // Read its first child address
    first_child_address = p->nextChildAddress;
    
    // Check if there are stored credentials
    if (first_child_address == NODE_ADDR_NULL)
    {
        guiDisplayInformationOnScreenAndWait(ID_STRING_NO_CREDS);
        return NODE_ADDR_NULL;
    }
    
    // Read child node
    readChildNode(c, first_child_address);
    
    // Check if there's only one child, that's a confirmation screen
    if (c->nextChildAddress == NODE_ADDR_NULL)
    {
        confirmationText_t temp_conf_text;
        
        // Prepare asking confirmation screen
        temp_conf_text.lines[0] = readStoredStringToBuffer(ID_STRING_CONFACCESSTO);
        temp_conf_text.lines[1] = (char*)p->service;
        temp_conf_text.lines[2] = readStoredStringToBuffer(ID_STRING_WITHTHISLOGIN);
        temp_conf_text.lines[3] = (char*)c->login;
        
        // Prompt user for confirmation, flash the screen
        if ((bypass_confirmation == TRUE) || (guiAskForConfirmation(0xF0 | 4, &temp_conf_text) == RETURN_OK))
        {
            picked_child = first_child_address;
        }
    }
    else
    {
        temp_child_address = first_child_address;
        uint8_t action_chosen = FALSE;
        
        while (action_chosen == FALSE)
        {
            // Draw asking bitmap
            oledBitmapDrawFlash(0, 0, BITMAP_LOGIN, 0);
            
            // Write domain name on screen
            char temp_string[INDEX_TRUNCATE_SERVICE_CENTER+1];
            memcpy(temp_string, (char*)p->service, sizeof(temp_string));
            temp_string[INDEX_TRUNCATE_SERVICE_CENTER] = 0;
            oledPutstrXY(0, 24, OLED_CENTRE, temp_string);
            
            // Clear led_mask
            led_mask = 0;
            i = 0;
            
            // List logins on screen
            while ((temp_child_address != NODE_ADDR_NULL) && (i != 4))
            {
                // Read child node to get login
                readChildNode(c, temp_child_address);
                
                // Print Login at the correct slot
                displayCredentialAtSlot(i, (char*)c->login, INDEX_TRUNCATE_LOGIN_FAV);            
                
                // Store address in array, fetch next address
                addresses[i] = temp_child_address;
                temp_child_address = c->nextChildAddress;
                i++;
            }
            
            // If nothing after, hide right arrow
            if ((i != 4) || (c->nextChildAddress == NODE_ADDR_NULL))
            {
                oledFillXY(177, 25, 16, 14, 0x00);
                led_mask |= LED_MASK_RIGHT;
            }
            
            // Light only the available choices
            for (j = i; j < 4; j++)
            {
                led_mask |= (1 << j);
            }
            
            // Display picture
            oledDisplayOtherBuffer();
            
            // Get touched quarter
            j = getTouchedPositionAnswer(led_mask);
            
            // Check its validity, knowing that by default we will return NODE_ADDR_NULL
            if (j == -1)
            {
                // Time out
                action_chosen = TRUE;
            }
            else if (j < i)
            {
                picked_child = addresses[j];
                action_chosen = TRUE;
            }
            else if (j == TOUCHPOS_LEFT)
            {                
                // If there is a previous children, go back 4 indexes
                if (addresses[0] != first_child_address)
                {
                    c->prevChildAddress = addresses[0];
                    for (i = 0; i < 5; i++)
                    {
                        temp_child_address = c->prevChildAddress;
                        readChildNode(c, temp_child_address);
                    }
                }
                else
                {
                    // otherwise, return
                    action_chosen = TRUE;
                }
            }
            else if ((j == TOUCHPOS_RIGHT) && (i == 4) && (c->nextChildAddress != NODE_ADDR_NULL))
            {
                // If there are more nodes to display, let it loop
                // temp_child_address = c->nextChildAddress;
            }
            else
            {
                // Wrong position
                temp_child_address = addresses[0];
            }
        }
    }
    
    return picked_child;
}
/*! \fn     guiScreenLoop(uint8_t input_interface_result)
*   \brief  Function called to handle screen changes
*   \param  input_interface_result Touch detection result
*/
void guiScreenLoop(uint8_t input_interface_result)
{
    // If no press, you can return!
    if ((input_interface_result == WHEEL_ACTION_NONE) || (currentScreen == SCREEN_DEFAULT_INSERTED_INVALID) || (currentScreen == SCREEN_DEFAULT_INSERTED_UNKNOWN))
    {
        return;
    }

    if (currentScreen == SCREEN_DEFAULT_NINSERTED)
    {
        // No smart card inserted, ask the user to insert one
        guiDisplayInsertSmartCardScreenAndWait();
    }
    else if (currentScreen == SCREEN_MEMORY_MGMT)
    {
        // Currently in memory management mode, tell the user to finish it via the plugin/app
        guiDisplayInformationOnScreenAndWait(ID_STRING_CLOSEMEMMGMT);
        guiGetBackToCurrentScreen();
        miniWheelClearDetections();
    }
    else if (currentScreen == SCREEN_DEFAULT_INSERTED_LCK)
    {
        // Locked screen and a detection happened, check that the user hasn't removed his card, launch unlocking process
        if ((cardDetectedRoutine() == RETURN_MOOLTIPASS_USER) && (validCardDetectedFunction(0, TRUE) == RETURN_VCARD_OK))
        {
            // User approved his pin
            unlockFeatureCheck();
            currentScreen = SCREEN_DEFAULT_INSERTED_NLCK;
        }
            
        // Go to the new screen
        guiGetBackToCurrentScreen();
    }
    else
    {
        if (input_interface_result == WHEEL_ACTION_UP)
        {
            // We can do that because of defines and bitmap order (see logic_fw_flash_storage and gui.h)
            if (currentScreen == SCREEN_LOCK)
            {
                currentScreen = SCREEN_SETTINGS;
            } 
            else if (currentScreen == SCREEN_SETTINGS_CHANGE_PIN)
            {
                currentScreen = SCREEN_SETTINGS_ERASE;
            }
            else
            {
                currentScreen--;
            }
            // We can do that because of defines and bitmap order (see logic_fw_flash_storage and gui.h)
            for (uint8_t i = 0; i < NB_BMPS_PER_TRANSITION; i++)
            {
                miniOledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK+NB_BMPS_PER_TRANSITION-1-i, OLED_SCROLL_FLIP);
                timerBasedDelayMs(12);
            }
        }
        else if (input_interface_result == WHEEL_ACTION_DOWN)
        {
            // We can do that because of defines and bitmap order (see logic_fw_flash_storage and gui.h)
            for (uint8_t i = 0; i < NB_BMPS_PER_TRANSITION-1; i++)
            {
                miniOledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK+1+i, OLED_SCROLL_FLIP);
                timerBasedDelayMs(12);
            }
            if (currentScreen == SCREEN_SETTINGS)
            {
                currentScreen = SCREEN_LOCK;
            }
            else if (currentScreen == SCREEN_SETTINGS_ERASE)
            {
                currentScreen = SCREEN_SETTINGS_CHANGE_PIN;
            }
            else
            {
                currentScreen++;
            }
            miniOledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK, OLED_SCROLL_FLIP);              
        }
        else if (input_interface_result == WHEEL_ACTION_LONG_CLICK)
        {
            // Long press in main menu : lock, long press in settings menu: go back to login screen
            if ((currentScreen >= SCREEN_SETTINGS_CHANGE_PIN) && (currentScreen <= SCREEN_SETTINGS_ERASE))
            {
                currentScreen = SCREEN_LOGIN;
                miniOledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK, OLED_SCROLL_UP);
            }
        }
        else if (input_interface_result == WHEEL_ACTION_SHORT_CLICK)
        {
            switch(currentScreen)
            {
                case SCREEN_LOCK:
                {
                    // User wants to lock his mooltipass
                    currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                    handleSmartcardRemoved();
                    guiGetBackToCurrentScreen();
                    break;
                }
                case SCREEN_LOGIN:
                {
                    // User wants to go to the login menu
                    if (getStartingParentAddress() != NODE_ADDR_NULL)
                    {
                        loginSelectLogic();
                    }
                    else
                    {
                        guiDisplayInformationOnScreenAndWait(ID_STRING_NO_CREDS);
                    }
                    guiGetBackToCurrentScreen();
                    break;
                }
                case SCREEN_FAVORITES:
                {
                    // User wants to go to the favorite menu
                    #if defined(ENABLE_CREDENTIAL_MANAGEMENT) && defined(REPLACE_FAVORITES_WITH_CREDENTIAL_MANAGEMENT)
                        managementActionPickingLogic();
                    #else
                        favoritePickingLogic();
                    #endif
                    guiGetBackToCurrentScreen();
                    break;
                }
                case SCREEN_SETTINGS:
                {
                    currentScreen = SCREEN_SETTINGS_CHANGE_PIN;
                    miniOledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK, OLED_SCROLL_UP);
                    break;
                }
                case SCREEN_SETTINGS_HOME:
                {
                    currentScreen = SCREEN_LOGIN;
                    miniOledBitmapDrawFlash(0, 0, (currentScreen-SCREEN_LOCK)*NB_BMPS_PER_TRANSITION+BITMAP_MAIN_LOCK, OLED_SCROLL_UP);
                    break;
                }
                case SCREEN_SETTINGS_CHANGE_PIN:
                {
                    // User wants to change his PIN code
                        
                    // Reauth user
                    if (removeCardAndReAuthUser() == RETURN_OK)
                    {
                        // User approved his pin, ask his new one
                        volatile uint16_t pin_code;
                            
                        if (guiAskForNewPin(&pin_code, ID_STRING_NEW_PINQ) == RETURN_NEW_PIN_OK)
                        {
                            // User successfully entered a new pin
                            writeSecurityCode(&pin_code);
                            // Inform of success
                            guiDisplayInformationOnScreenAndWait(ID_STRING_PIN_CHANGED);
                        }
                        else
                        {
                            // Inform of fail
                            guiDisplayInformationOnScreenAndWait(ID_STRING_PIN_NCGHANGED);
                        }
                        pin_code = 0x0000;
                    }
                    else
                    {
                        currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                    }
                    guiGetBackToCurrentScreen();
                    break;
                }
                case SCREEN_SETTINGS_BACKUP:
                {
                    // User wants to clone his smartcard
                    volatile uint16_t pin_code;
                    RET_TYPE temp_rettype;
                        
                    // Reauth user
                    if (removeCardAndReAuthUser() == RETURN_OK)
                    {
                        // Ask for new pin
                        temp_rettype = guiAskForNewPin(&pin_code, ID_STRING_PIN_NEW_CARD);
                        if (temp_rettype == RETURN_NEW_PIN_OK)
                        {
                            // Start the cloning process
                            if (cloneSmartCardProcess(&pin_code) == RETURN_OK)
                            {
                                // Well it worked....
                            }
                            else
                            {
                                currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                                guiDisplayInformationOnScreen(ID_STRING_TGT_CARD_NBL);
                            }
                            pin_code = 0x0000;
                        }
                        else if (temp_rettype == RETURN_NEW_PIN_DIFF)
                        {
                            currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                            guiDisplayInformationOnScreen(ID_STRING_PIN_DIFF);
                        }
                        else
                        {
                            guiGetBackToCurrentScreen();
                            return;
                        }
                    }
                    else
                    {
                        currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                        guiDisplayInformationOnScreen(ID_STRING_FAILED);
                    }
                    userViewDelay();
                    guiGetBackToCurrentScreen();
                    break;
                }
                case SCREEN_SETTINGS_ERASE:
                {
                    // User wants to delete his profile in flash / eeprom....
                    if ((guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_AREYOUSURE)) == RETURN_OK) && (removeCardAndReAuthUser() == RETURN_OK) && (guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_AREYOURLSURE)) == RETURN_OK))
                    {
                        uint8_t currentuserid = getCurrentUserID();
                        guiDisplayProcessingScreen();
                        deleteCurrentUserFromFlash();
                            
                        if (guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_ERASE_TCARD)) == RETURN_OK)
                        {
                            guiDisplayProcessingScreen();
                            eraseSmartCard();
                                
                            // Erase other smartcards
                            while (guiAskForConfirmation(1, (confirmationText_t*)readStoredStringToBuffer(ID_STRING_OTHECARDFUSER)) == RETURN_OK)
                            {
                                // Ask the user to insert other smartcards
                                guiDisplayInformationOnScreen(ID_STRING_INSERT_OTHER);
                                    
                                // Wait for the user to remove and enter another smartcard
                                while (isCardPlugged() != RETURN_JRELEASED);
                                    
                                // Wait for the user to insert a new smart card
                                while (isCardPlugged() != RETURN_JDETECT);
                                guiDisplayProcessingScreen();
                                    
                                // Check the card type & ask user to enter his pin, check that the new user id loaded by validCardDetectedFunction is still the same
                                if ((cardDetectedRoutine() == RETURN_MOOLTIPASS_USER) && (validCardDetectedFunction(0, FALSE) == RETURN_VCARD_OK) && (currentuserid == getCurrentUserID()))
                                {
                                    eraseSmartCard();
                                }
                            }
                        }
                            
                        // Delete LUT entries
                        guiDisplayProcessingScreen();
                        deleteUserIdFromSMCUIDLUT(currentuserid);
                            
                        // Go to invalid screen
                        currentScreen = SCREEN_DEFAULT_INSERTED_INVALID;
                    }
                    else
                    {
                        currentScreen = SCREEN_DEFAULT_INSERTED_LCK;
                    }
                    userViewDelay();
                    handleSmartcardRemoved();
                    guiGetBackToCurrentScreen();
                    break;
                }

                default: break;
            }                
        }
    }
}