1"""ISO7816-9 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
29iso7816_9SW = {
30    0x62: (smartcard.sw.SWExceptions.WarningProcessingException,
31           {0x82: "End of file/record reached"}),
32
33    0x64: (smartcard.sw.SWExceptions.ExecutionErrorException,
34           {0x00: "Execution error"}),
35
36    0x69: (smartcard.sw.SWExceptions.CheckingErrorException,
37           {0x82: "Security status not satisfied"}),
38
39    0x6A: (smartcard.sw.SWExceptions.CheckingErrorException,
40           {0x80: "Incorrect parameters in data field",
41            0x84: "Not enough memory space",
42            0x89: "File already exists",
43            0x8A: "DF name already exists"}),
44}
45
46
47class ISO7816_9ErrorChecker(ErrorChecker):
48    """ISO7816-8 error checker.
49
50    This error checker raises the following exceptions:
51      - sw1 sw2
52      - 62  82          WarningProcessingException
53      - 64  00          ExecutionErrorException
54      - 69  82          CheckingErrorException
55      - 6A  80,84,89,8A CheckingErrorException
56
57    This checker does not raise exceptions on undefined sw1 values, e.g.:
58      - sw1 sw2
59      - 63  any
60      - 6F  any
61
62    and on undefined sw2 values, e.g.:
63      - sw1 sw2
64      - 62  81 83
65      - 64  any except 00
66
67
68    Use another checker in the error checking chain, e.g., the
69    ISO7816_4SW1ErrorChecker or ISO7816_4ErrorChecker, to raise
70    exceptions on these undefined values.
71    """
72
73    def __call__(self, data, sw1, sw2):
74        """Called to test data, sw1 and sw2 for error.
75
76        @param data:       apdu response data
77        @param sw1, sw2:   apdu data status words
78
79        Derived classes must raise a L{smartcard.sw.SWException} upon error."""
80        if sw1 in iso7816_9SW:
81            exception, sw2dir = iso7816_9SW[sw1]
82            if type(sw2dir) == type({}):
83                try:
84                    message = sw2dir[sw2]
85                    raise exception(data, sw1, sw2, message)
86                except KeyError:
87                    pass
88
89
90if __name__ == '__main__':
91    """Small sample illustrating the use of ISO7816_9ErrorChecker."""
92    ecs = ISO7816_9ErrorChecker()
93    ecs([], 0x90, 0x00)
94    ecs([], 0x6a, 0x81)
95    try:
96        ecs([], 0x6A, 0x8A)
97    except smartcard.sw.SWExceptions.CheckingErrorException as e:
98        print(str(e) + " %x %x" % (e.sw1, e.sw2))
99