1"""Open Platform 2.1 error checker.
2
3__author__ = "http://www.gemalto.com"
4
5Copyright 2001-2012 gemalto
6Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com
7
8This file is part of pyscard.
9
10pyscard is free software; you can redistribute it and/or modify
11it under the terms of the GNU Lesser General Public License as published by
12the Free Software Foundation; either version 2.1 of the License, or
13(at your option) any later version.
14
15pyscard is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18GNU Lesser General Public License for more details.
19
20You should have received a copy of the GNU Lesser General Public License
21along with pyscard; if not, write to the Free Software
22Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23"""
24
25from __future__ import print_function
26from smartcard.sw.ErrorChecker import ErrorChecker
27import smartcard.sw.SWExceptions
28
29op21_SW = {
30    0x62: (smartcard.sw.SWExceptions.WarningProcessingException,
31           {0x83: "Card life cycle is CARD_LOCKED"}),
32
33    0x63: (smartcard.sw.SWExceptions.WarningProcessingException,
34           {0x00: "Authentication failed"}),
35
36    0x64: (smartcard.sw.SWExceptions.ExecutionErrorException,
37           {0x00: "Execution error"}),
38
39    0x65: (smartcard.sw.SWExceptions.ExecutionErrorException,
40           {0x81: "Memory failure"}),
41
42    0x67: (smartcard.sw.SWExceptions.CheckingErrorException,
43           {0x00: "Wrong length in Lc"}),
44
45    0x69: (smartcard.sw.SWExceptions.CheckingErrorException,
46           {0x82: "Security status not satisfied",
47            0x85: "Conditions of use not satisfied"}),
48
49    0x6A: (smartcard.sw.SWExceptions.CheckingErrorException,
50           {0x80: "Incorrect values in command data",
51            0x81: "Function not supported",
52            0x82: "Application not found",
53            0x84: "Not enough memory space",
54            0x86: "Incorrect parameters P1-P2",
55            0x88: "Referenced data not found"}),
56
57    0x6D: (smartcard.sw.SWExceptions.CheckingErrorException,
58           {0x00: "Instruction not supported"}),
59
60    0x6E: (smartcard.sw.SWExceptions.CheckingErrorException,
61           {0x00: "Class not supported"}),
62
63    0x94: (smartcard.sw.SWExceptions.CheckingErrorException,
64           {0x84: "Algorithm not supported",
65            0x85: "Invalid key check value"}),
66
67}
68
69
70class op21_ErrorChecker(ErrorChecker):
71    """Open platform 2.1 error checker.
72
73    This error checker raises the following exceptions:
74      - sw1 sw2
75      - 62  83                  WarningProcessingException
76      - 63  00                  WarningProcessingException
77      - 64  00                  ExecutionErrorException
78      - 65  81                  ExecutionErrorException
79      - 67  00                  CheckingErrorException
80      - 69  82 85               CheckingErrorException
81      - 6A  80 81 82 84 86 88   CheckingErrorException
82      - 6D  00                  CheckingErrorException
83      - 6E  00                  CheckingErrorException
84      - 94  84 85               CheckingErrorException
85
86    This checker does not raise exceptions on undefined sw1 values, e.g.:
87      - sw1 sw2
88      - 63  any
89      - 6F  any
90
91    and on undefined sw2 values, e.g.:
92      - sw1 sw2
93      - 62  81 83
94      - 64  any except 00
95
96
97    Use another checker in the error checking chain to raise exceptions
98    on these undefined values.
99    """
100
101    def __call__(self, data, sw1, sw2):
102        """Called to test data, sw1 and sw2 for error.
103
104        @param data:       apdu response data
105        @param sw1, sw2:   apdu data status words
106
107        Derived classes must raise a L{smartcard.sw.SWException} upon error."""
108        if sw1 in op21_SW:
109            exception, sw2dir = op21_SW[sw1]
110            if type(sw2dir) == type({}):
111                try:
112                    message = sw2dir[sw2]
113                    raise exception(data, sw1, sw2, message)
114                except KeyError:
115                    pass
116
117
118if __name__ == '__main__':
119    """Small sample illustrating the use of op21_ErrorChecker."""
120    ecs = op21_ErrorChecker()
121    ecs([], 0x90, 0x00)
122    ecs([], 0x94, 0x81)
123    try:
124        ecs([], 0x94, 0x84)
125    except smartcard.sw.SWExceptions.CheckingErrorException as e:
126        print(str(e) + "%x %x" % (e.sw1, e.sw2))
127