Merge remote branch 'upstream/master' into cardos5

This commit is contained in:
Jean-Pierre Szikora 2013-06-21 10:35:21 +02:00
commit ac96e73c8c
96 changed files with 2304 additions and 1565 deletions

66
.gitignore vendored
View File

@ -44,6 +44,7 @@ stamp-h*
*.rc
*.pc
*~
*.o
*.gz
*.bz2
*.[0-9]
@ -53,24 +54,47 @@ stamp-h*
*.out
*.tmp
ChangeLog
opensc.conf
xsl-stylesheets
opensc-config
test-conf
pkcs15-tool
pkcs15-crypt
pkcs15-init
piv-tool
eidenv
opensc-explorer
opensc-tool
rutoken-tool
cardos-info
cryptoflex-tool
netkey-tool
pkcs11-tool
pintest
p15dump
prngtest
base64
lottery
etc/opensc.conf.win
etc/opensc.conf
src/common/compat_getopt_main
src/minidriver/opensc-minidriver.inf
src/tools/cardos-tool
src/tools/iasecc-tool
src/tools/openpgp-tool
src/tools/sc-hsm-tool
src/tools/westcos-tool
src/tools/pkcs15-tool
src/tools/pkcs15-crypt
src/tools/pkcs15-init
src/tools/piv-tool
src/tools/eidenv
src/tools/opensc-explorer
src/tools/opensc-tool
src/tools/rutoken-tool
src/tools/cardos-info
src/tools/cryptoflex-tool
src/tools/netkey-tool
src/tools/pkcs11-tool
win32/OpenSC.iss
win32/OpenSC.wxs
win32/winconfig.h
MacOSX/build-package
*.dmg
*.pkg
OpenSC.tokend/
build/
engine_pkcs11/
libp11/
target/
src/scconf/test-conf
src/tests/base64
src/tests/lottery
src/tests/p15dump
src/tests/pintest
src/tests/prngtest

View File

@ -1,116 +0,0 @@
#!/usr/bin/perl
my $SYSTEM_VERS = "/System/Library/CoreServices/SystemVersion.plist";
my $EXIT_VALUE = 0;
if ( $ENV{OS_INSTALL} == 1) {
exit (0);
}
DO_CHECKS: {
# 10.5.8 or higher system must be active
if(CheckVersion("$SYSTEM_VERS", "10.5.8", "ProductVersion", "<")) {
$EXIT_VALUE = ((1 << 6) | ( 1 << 5 ) | 17 );
last;
}
# 10.5 system must be active
if(CheckVersion("$SYSTEM_VERS", "10.6", "ProductVersion", ">")) {
$EXIT_VALUE = ((1 << 6) | ( 1 << 5 ) | 18 );
last;
}
}
exit($EXIT_VALUE);
###
sub CheckVersion
{
my $path = $_[0];
my $version = $_[1];
my $keyName = $_[2];
my $operator = $_[3];
if (! -e $path) {
return 0;
}
if (!$operator) {
$operator = "==";
}
my $oldSeperator = $/;
$/ = \0;
open( PLIST, "$path") || do {
return 0;
};
$plistData = <PLIST>;
$plistData =~ /<dict>(.*?)<\/dict>/gis;
@items = split(/<key>/, $plistData);
shift @items;
foreach $item (@items) {
$item =~ /(.*?)<\/key>.*?<string>(.*?)<\/string>/gis;
$versiondata{ $1 } = $2;
}
close(PLIST);
$/ = $oldSeperator;
@theVersionArray = split(/\./, $versiondata{$keyName});
for ($i = 0; $i < 3; $i++) {
if(!$theVersionArray[$i]) {
$theVersionArray[$i] = '0';
}
}
@versionArray = split(/\./, $version);
my $actualVersion;
for ($i = 0; $i < 3; $i++) {
if (($theVersionArray[$i] != $versionArray[$i]) or ($i == 2)) {
$actualVersion = $theVersionArray[$i];
$version = $versionArray[$i];
last;
}
}
my $expression = '$actualVersion ' . $operator . ' $version';
if( eval ($expression) )
{
return 1;
}
else
{
return 0;
}
}
sub CheckIOReg
{
$RESULT = 0;
open(IOREGOUT, "/usr/sbin/ioreg |");
foreach $LINE (<IOREGOUT>) {
$BUF .= $LINE;
}
close(IOREGOUT);
foreach $ITEM (@_) {
if($BUF =~ /$ITEM/g) {
$RESULT = 1;
last;
}
}
return($RESULT);
}

View File

@ -1,25 +0,0 @@
#!/bin/bash
if !([ -e "/usr/lib/opensc-pkcs11.so" ])
then
ln -s /Library/OpenSC/lib/opensc-pkcs11.so /usr/lib/opensc-pkcs11.so
fi
if [ -e "/Library/OpenSC/etc/opensc.conf.md5" ]
then
read cs_fromfile file < "/Library/OpenSC/etc/opensc.conf.md5"
cs_calculated=$( md5 -q "/Library/OpenSC/etc/opensc.conf")
if [ "$cs_fromfile" = "$cs_calculated" ]
then
mv /Library/OpenSC/etc/opensc.conf.orig /Library/OpenSC/etc/opensc.conf
md5 -r /Library/OpenSC/etc/opensc.conf > /Library/OpenSC/etc/opensc.conf.md5
fi
else
mv /Library/OpenSC/etc/opensc.conf.orig /Library/OpenSC/etc/opensc.conf
md5 -r /Library/OpenSC/etc/opensc.conf > /Library/OpenSC/etc/opensc.conf.md5
fi
for f in /Library/OpenSC/bin/*
do
ln -sf $f /usr/local/bin
done
exit 0

View File

@ -1,170 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>EST Install OpenSC</title>
<style type="text/css">
body { font: 12px Helvetica; }
h1 { font-size: 16px; }
h2 { font-size: 13px; padding-bottom: 5px; padding-top: 5px; }
p { padding: 10px; }
</style>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
<h1 style="text-align: center;">GNU LESSER GENERAL PUBLIC LICENSE</h1>
<p style="text-align: center;">Version 2.1, February 1999</p>
<blockquote>
<p>Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.</p>
<p>[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]</p></blockquote>
<h3>Preamble</h3>
<p> The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. </p>
<p>This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.
</p>
<p> When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.</p>
<p>To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.
</p>
<p> For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. </p>
<p>We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. </p>
<p>To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. </p>
<p>
Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. </p>
<p>Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. </p>
<p>When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. </p>
<p>We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. </p>
<p>For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.
</p>
<p>In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. </p>
<p> Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.
</p>
<p>The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. </p>
<h3>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</h3>
<p><strong>0.</strong> This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".</p>
<p> A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. </p>
<p> The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) </p>
<p> "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.</p>
<p>Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. </p>
<p><strong>1.</strong> You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.
</p>
<p> You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. </p>
<p><strong>2.</strong> You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:
</p>
<blockquote>
<p>a) The modified work must itself be a software library. </p>
<p>b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.</p>
<p>c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. </p>
<p>d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. </p>
<p> (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)
</p>
<p> These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.
</p>
<p>Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.
</p>
<p> In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
</p></blockquote>
<p><strong>3.</strong> You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. </p>
<p>Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.
</p>
<p> This option is useful when you wish to copy part of the code of the Library into a program that is not a library.
</p>
<p><strong>4.</strong> You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.
</p>
<p>If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.</p>
<p><strong>5.</strong> A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. </p>
<p> However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. </p>
<p> When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. </p>
<p> If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) </p>
<p>Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. </p>
<p><strong>6.</strong> As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. </p>
<p>
You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: </p>
<blockquote><p>a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) </p>
<p>b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. </p>
<p>
c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. </p>
<p>d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. </p>
<p>e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.</p>
</blockquote>
<p>For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. </p>
<p> It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. </p>
<p><strong>7.</strong> You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: </p>
<blockquote>
<p>a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. </p>
<p>b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.</p></blockquote>
<p><strong>8.</strong> You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. </p>
<p>
<strong>9.</strong> You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. </p>
<p>
<strong>10.</strong> Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. </p>
<p><strong>11.</strong> If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. </p>
<p>
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. </p>
<p>It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. </p>
<p>This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. </p>
<p>
<strong>12.</strong> If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. </p>
<p>
<strong>13.</strong> The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.</p>
<p>Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. </p>
<p>
<strong>14.</strong> If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. </p>
<p>
NO WARRANTY </p>
<p>
<strong>15. </strong>BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. </p>
<p>
<strong>16.</strong> IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. </p>
</body>
</html>

View File

@ -1,26 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
body { font: 12px Helvetica; }
h1 { font-size: 16px; }
h2 { font-size: 13px; padding-bottom: 5px; padding-top: 5px; }
p { padding: 10px; }
</style>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
<h1>OpenSC, version @PACKAGE_VERSION@</h1>
<p>for Mac OS X 10.6 (Snow Leopard) and 10.7 (Lion), universal (32-bit and 64-bit)</p>
<p>OpenSC provides a set of libraries and utilities to work with smart cards. Its main focus is on cards that support cryptographic operations, and facilitate their use in security applications such as authentication, mail encryption and digital signatures.</p>
<p>OpenSC implements the <a href="http://www.rsa.com/rsalabs/node.asp?id=2133">PKCS#11 API</a> so applications supporting this API (such as Mozilla Firefox and Thunderbird) can use it. On the card OpenSC implements the <a href="http://www.rsa.com/rsalabs/node.asp?id=2141">PKCS#15</a> standard and aims to be compatible with every software/card that does so, too.</p>
<h2>Documentation:</h2>
<p>The OpenSC Wiki is available at: <a href="http://www.opensc-project.org/opensc">http://www.opensc-project.org/opensc</a> and should be consulted for further documentation and support.</p>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,18 +1,10 @@
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
EXTRA_DIST = build build-package.in libtool-bundle opensc-uninstall \
10.5/resources \
10.5/resources/background.jpg \
10.5/resources/InstallationCheck.strings \
10.5/resources/License.html \
10.5/resources/ReadMe.html.in \
10.5/scripts \
10.5/scripts/InstallationCheck \
10.5/scripts/postflight \
10.6/resources \
10.6/resources/background.jpg \
10.6/resources/InstallationCheck.strings \
10.6/resources/License.html \
10.6/resources/ReadMe.html.in \
10.6/scripts \
10.6/scripts/InstallationCheck \
10.6/scripts/postflight
resources \
resources/background.jpg \
resources/InstallationCheck.strings \
resources/License.html \
resources/ReadMe.html.in \
scripts \
scripts/InstallationCheck \
scripts/postflight

View File

@ -1,52 +1,42 @@
#!/bin/bash
# Building the installer is only tested and supported on 10.7 with Xcode 4.2.1
# Built package targets 10.6, 10.7 and 10.8
# Building should also work on other versions, YMMV
set -ex
OSX_RELEASE=${1:-10.6}
INTEL_ONLY=${INTEL_ONLY:-no}
test -x ./configure || ./bootstrap
BUILDPATH=${PWD}
case ${OSX_RELEASE} in
"10.5")
if test ${INTEL_ONLY} = "yes"; then
export CFLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -arch i386 -mmacosx-version-min=10.5 -g"
else
export CFLAGS="-isysroot /Developer/SDKs/MacOSX10.5.sdk -arch i386 -arch ppc7400 -mmacosx-version-min=10.5 -g"
fi
;;
"10.6")
export CFLAGS="-isysroot /Developer/SDKs/MacOSX10.6.sdk -arch i386 -arch x86_64 -mmacosx-version-min=10.6 -g"
# Use new locations for SDK on 10.8 with Xcode 4.6 (?)
OSX_RELEASE=`sw_vers -productVersion`
case ${OSX_RELEASE:0:4} in
"10.8")
SYSROOT="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk"
PKGMAKER="/Applications/PackageMaker.app/Contents/MacOS/PackageMaker"
;;
*)
echo "OSX ${OSX_RELEASE} is not supported!"
exit 1
SYSROOT="/Developer/SDKs/MacOSX10.6.sdk"
PKGMAKER="/Developer/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker"
;;
esac
export CFLAGS="-isysroot $SYSROOT -arch i386 -arch x86_64 -mmacosx-version-min=10.6"
export SED=/usr/bin/sed
PREFIX=/Library/OpenSC
export PKG_CONFIG_PATH=/usr/lib/pkgconfig
# In case of OSX 10.5, link against static libltdl to work around
# missing libltdl.3.dylib in 10.5 PPC version
test ${OSX_RELEASE} = "10.5" && export LTLIB_LIBS="/Developer/SDKs/MacOSX10.5.sdk/usr/lib/libltdl.a"
./configure --prefix=$PREFIX \
--sysconfdir=$PREFIX/etc \
--disable-dependency-tracking \
--enable-shared \
--disable-static \
--enable-strict \
--disable-assert
--disable-assert \
--enable-sm # TODO: remove this
# check if make install is required
case "${OSX_RELEASE}" in
"10.5") if test ${INTEL_ONLY} = "yes"; then required_arch="i386"; else required_arch="ppc7400"; fi ;;
"10.6") required_arch="x86_64" ;;
esac
if !(test -e src/libopensc/.libs/libopensc.dylib && (file src/libopensc/.libs/libopensc.dylib | grep $required_arch)); then
make clean
fi
# always make clean
make clean
# compile
make -j 2
@ -61,52 +51,35 @@ rm -f target/Library/OpenSC/lib/*.la
# generate .bundle (required by Adobe Acrobat)
./MacOSX/libtool-bundle target/Library/OpenSC/lib/opensc-pkcs11.so target/Library/OpenSC/lib
if test ${OSX_RELEASE} = "10.6"; then
# Build libp11+engine_pkcs11. Attention! Uses modified branches from github!
test -d libp11 || git clone http://github.com/martinpaljak/libp11.git -b martin
(cd libp11
test -x confiure || ./bootstrap
./configure --enable-static --disable-shared --disable-dependency-tracking --prefix=${BUILDPATH}/build && make && make install
cd ..)
test -d engine_pkcs11 || git clone http://github.com/martinpaljak/engine_pkcs11.git -b martin
(cd engine_pkcs11
git checkout origin/martin
test -x configure || ./bootstrap
PKG_CONFIG_PATH=${BUILDPATH}/build/lib/pkgconfig:${PKG_CONFIG_PATH} ./configure --disable-dependency-tracking --prefix=/Library/OpenSC && make
make install DESTDIR=${BUILDPATH}/target)
fi
# Build engine_pkcs11 + libp11
test -d libp11 || git clone http://github.com/OpenSC/libp11.git
(cd libp11
test -x confiure || ./bootstrap
./configure --enable-static --disable-shared --disable-dependency-tracking --prefix=${BUILDPATH}/build && make && make install)
test -d engine_pkcs11 || git clone http://github.com/OpenSC/engine_pkcs11.git
(cd engine_pkcs11
test -x configure || ./bootstrap
PKG_CONFIG_PATH=${BUILDPATH}/build/lib/pkgconfig:${PKG_CONFIG_PATH} ./configure --disable-dependency-tracking --prefix=/Library/OpenSC && make install DESTDIR=${BUILDPATH}/target)
# Check out OpenSC.tokend, if not already fetched.
if ! test -e OpenSC.tokend; then
git clone http://github.com/martinpaljak/OpenSC.tokend.git
git clone http://github.com/OpenSC/OpenSC.tokend.git
fi
# refresh remote branches, in case the script has changed the active branch and existing buildslave checkout is used.
git --git-dir OpenSC.tokend/.git --work-tree OpenSC.tokend fetch --all
# Fetch binary dependencies
if ! test -f build-10.6.tar.gz; then
curl -O https://www.opensc-project.org/downloads/build-10.6.tar.gz
fi
case "${OSX_RELEASE}" in
"10.5") git --git-dir OpenSC.tokend/.git --work-tree OpenSC.tokend checkout --force origin/10.5-0.12.2; rm -rf OpenSC.tokend/build
if test ${INTEL_ONLY} = "yes"; then
sed -e 's/ ppc7400//g' OpenSC.tokend/Tokend.xcodeproj/project.pbxproj > project.tmp
mv project.tmp OpenSC.tokend/Tokend.xcodeproj/project.pbxproj
fi
;;
"10.6") git --git-dir OpenSC.tokend/.git --work-tree OpenSC.tokend checkout --force origin/10.6-0.12.2; rm -rf OpenSC.tokend/build ;;
esac
if ! test -e build-${OSX_RELEASE}.tar.gz; then
case ${OSX_RELEASE} in
"10.5")
curl http://martinpaljak.net/download/build-10.5.tar.gz -o build-${OSX_RELEASE}.tar.gz
;;
"10.6")
curl http://martinpaljak.net/download/build-10.6.tar.gz -o build-${OSX_RELEASE}.tar.gz
;;
esac
# Check for correctness
if ! test $(md5 -q build-10.6.tar.gz) == "5686fb4dda6e9f1f07d06293a25fdd37"; then
echo "MD5 of binary components does not match!"
exit 1
fi
# Unpack the binary building components
if ! test -e OpenSC.tokend/build; then
tar -C OpenSC.tokend -xzvf build-${OSX_RELEASE}.tar.gz
tar -C OpenSC.tokend -xzvf build-10.6.tar.gz
fi
# Create the symlink to OpenSC sources
@ -122,20 +95,20 @@ mkdir -p target/usr/local/bin
cp MacOSX/opensc-uninstall target/usr/local/bin
# Build installer package
/Developer/Applications/Utilities/PackageMaker.app/Contents/MacOS/PackageMaker \
${PKGMAKER} \
-r target \
-o OpenSC-@PACKAGE_VERSION@-${OSX_RELEASE}.pkg \
-t "OpenSC @PACKAGE_VERSION@ for Mac OS X ${OSX_RELEASE}" \
-o OpenSC-@PACKAGE_VERSION@.pkg \
-t "OpenSC @PACKAGE_VERSION@ for Mac OS X 10.6+" \
-i org.opensc-project.mac \
-n @PACKAGE_VERSION@ \
-g 10.4 \
-b \
-v \
--no-relocate \
-e MacOSX/${OSX_RELEASE}/resources \
-s MacOSX/${OSX_RELEASE}/scripts
-e MacOSX/resources \
-s MacOSX/scripts
# Create .dmg
rm -f OpenSC-@PACKAGE_VERSION@-${OSX_RELEASE}.dmg
rm -f OpenSC-@PACKAGE_VERSION@.dmg
TIMESTAMP=$(date +%Y.%m.%d)
hdiutil create -srcfolder OpenSC-@PACKAGE_VERSION@-${OSX_RELEASE}.pkg -volname "OpenSC @PACKAGE_VERSION@ for Mac OS X ${OSX_RELEASE} (${TIMESTAMP})" OpenSC-@PACKAGE_VERSION@-${OSX_RELEASE}.dmg
hdiutil create -srcfolder OpenSC-@PACKAGE_VERSION@.pkg -volname "OpenSC @PACKAGE_VERSION@ for Mac OS X 10.6+ (${TIMESTAMP})" OpenSC-@PACKAGE_VERSION@.dmg

View File

@ -6,20 +6,23 @@ if [ "$(id -u)" != "0" ]; then
exit 1
fi
# Remove symlinks to commands
for file in /Library/OpenSC/bin/*; do
test -L "/usr/local/bin/$(basename $file)" && rm -f "/usr/local/bin/$(basename $file)"
done
# Remove symlink for pkcs11
test -L /usr/lib/opensc-pkcs11.so && rm -f /usr/lib/opensc-pkcs11.so
# Remove installed files
rm -rf /Library/OpenSC
rm -rf /System/Library/Security/tokend/OpenSC.tokend
for file in /usr/lib/opensc-pkcs11.so /usr/local/bin/cardos-tool /usr/local/bin/cryptoflex-tool /usr/local/bin/eidenv /usr/local/bin/netkey-tool /usr/local/bin/opensc-explorer /usr/local/bin/opensc-tool /usr/local/bin/piv-tool /usr/local/bin/pkcs11-tool /usr/local/bin/pkcs15-crypt /usr/local/bin/pkcs15-init /usr/local/bin/pkcs15-tool /usr/local/bin/rutoken-tool /usr/local/bin/westcos-tool; do
test -L $file && rm -f $file
done
rm -f /usr/local/bin/opensc-uninstall
# delete receipts on 10.6
# delete receipts on 10.6+
for file in /var/db/receipts/org.opensc-project.mac.bom /var/db/receipts/org.opensc-project.mac.plist; do
test -f $file && rm -f $file
done
# delete receipts on 10.5
test -d /Library/Receipts/OpenSC-10.5.pkg && rm -rf /Library/Receipts/OpenSC-10.5.pkg
# remove this script
rm -f /usr/local/bin/opensc-uninstall
echo "OpenSC has been removed from your system. See you again!"

View File

@ -13,7 +13,7 @@
<h1>OpenSC, version @PACKAGE_VERSION@</h1>
<p>for Mac OS X 10.5 (Leopard), universal (32-bit i386 and ppc)</p>
<p>for Mac OS X 10.6+</p>
<p>OpenSC provides a set of libraries and utilities to work with smart cards. Its main focus is on cards that support cryptographic operations, and facilitate their use in security applications such as authentication, mail encryption and digital signatures.</p>

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -13,11 +13,6 @@ DO_CHECKS: {
$EXIT_VALUE = ((1 << 6) | ( 1 << 5 ) | 17 );
last;
}
# 10.6 or 10.7 system must be active
if(CheckVersion("$SYSTEM_VERS", "10.8", "ProductVersion", ">")) {
$EXIT_VALUE = ((1 << 6) | ( 1 << 5 ) | 18 );
last;
}
}
exit($EXIT_VALUE);

View File

@ -11,7 +11,7 @@ MAINTAINERCLEANFILES = \
$(srcdir)/m4/ltversion.m4 $(srcdir)/m4/lt~obsolete.m4 \
$(srcdir)/m4/ltoptions.m4 \
$(srcdir)/packaged
EXTRA_DIST = Makefile.mak svnignore
EXTRA_DIST = Makefile.mak
SUBDIRS = etc src win32 doc MacOSX

2
README
View File

@ -1,4 +1,4 @@
OpenSC documentation wiki is available online at
http://www.opensc-project.org/opensc/
https://github.com/OpenSC/OpenSC/wiki
Please take a look at the documentation before trying to use OpenSC.

View File

@ -243,7 +243,7 @@ AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_HEADER_ASSERT
AC_CHECK_HEADERS([ \
errno.h fcntl.h malloc.h stdlib.h \
errno.h fcntl.h stdlib.h \
inttypes.h string.h strings.h \
sys/time.h unistd.h getopt.h sys/mman.h
])
@ -286,12 +286,9 @@ AC_CHECK_LIB(
if test "${WIN32}" = "no"; then
dnl dl support
AC_CHECK_LIB(
[dl],
[dlopen],
,
[AC_MSG_ERROR([libdl required])]
)
AC_SEARCH_LIBS([dlopen], [dl dld], [], [
AC_MSG_ERROR([unable to find the dlopen() function])
])
dnl Special check for pthread support.
AX_PTHREAD(
@ -604,6 +601,8 @@ if test "$GCC" = "yes"; then
CFLAGS="-fno-strict-aliasing ${CFLAGS}"
fi
CFLAGS="${CFLAGS} -Werror=declaration-after-statement"
AC_CONFIG_FILES([
Makefile
doc/Makefile
@ -613,13 +612,14 @@ AC_CONFIG_FILES([
src/common/Makefile
src/libopensc/Makefile
src/libopensc/libopensc.pc
src/libsm/Makefile
src/pkcs11/Makefile
src/pkcs15init/Makefile
src/scconf/Makefile
src/tests/Makefile
src/tests/regression/Makefile
src/tools/Makefile
src/sm/Makefile
src/smm/Makefile
src/minidriver/Makefile
src/minidriver/opensc-minidriver.inf
win32/Makefile
@ -629,8 +629,7 @@ AC_CONFIG_FILES([
win32/OpenSC.wxs
MacOSX/Makefile
MacOSX/build-package
MacOSX/10.5/resources/ReadMe.html
MacOSX/10.6/resources/ReadMe.html
MacOSX/resources/ReadMe.html
])
AC_OUTPUT

View File

@ -57,7 +57,7 @@
<varlistentry>
<term>
<option>--print</option>,
<option>-n</option>
<option>-p</option>
</term>
<listitem><para>Prints all data
fields from the card, like validity

View File

@ -475,6 +475,15 @@
</listitem>
</varlistentry>
<varlistentry>
<term>
<command>sm</command> <replaceable>[open]</replaceable>|<replaceable>[close]</replaceable>
</term>
<listitem>
<para>Calls the card's <replaceable>open</replaceable> or <replaceable>close</replaceable> Secure Messaging handler.</para>
</listitem>
</varlistentry>
</variablelist>
</para>
</refsect1>

View File

@ -54,9 +54,10 @@
<option>-C</option> <replaceable>filename</replaceable>
</term>
<listitem>
<para>Create a DKEK share encrypted under a user supplied password and saved to the file
<para>Create a DKEK share encrypted under a password and save it to the file
given as parameter.</para>
<para>Use <option>--password</option> to provide a password for encryption rather than prompting for one.</para>
<para>Use <option>--pwd-shares-threshold</option> and <option>--pwd-shares-total</option> to randomly generate a password and split is using a (t, n) threshold scheme.</para>
</listitem>
</varlistentry>
@ -68,6 +69,7 @@
<listitem>
<para>Prompt for user password, read and decrypt DKEK share and import into SmartCard-HSM.</para>
<para>Use <option>--password</option> to provide a password for decryption rather than prompting for one.</para>
<para>Use <option>--pwd-shares-total</option> to specify the number of shares that should be entered to reconstruct the password.</para>
</listitem>
</varlistentry>
@ -151,6 +153,24 @@
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--pwd-shares-threshold</option> <replaceable>value</replaceable>
</term>
<listitem>
<para>Define threshold for number of password shares required for reconstruction.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--pwd-shares-total</option> <replaceable>value</replaceable>
</term>
<listitem>
<para>Define number of password shares.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<option>--force</option>
@ -194,13 +214,17 @@
<title>Examples</title>
<para>Create a DKEK share:</para>
<para><command>sc-hsm-tool --create-dkek-share dkek-share-1.pbe</command></para>
<para>Initialize SmartCard-HSM to use a single DKEK share</para>
<para>Create a DKEK share with random password split up using a (3, 5) threshold scheme:</para>
<para><command>sc-hsm-tool --create-dkek-share dkek-share-1.pbe --pwd-shares-threshold 3 --pwd-shares-total 5</command></para>
<para>Initialize SmartCard-HSM to use a single DKEK share:</para>
<para><command>sc-hsm-tool --initialize --so-pin 3537363231383830 --pin 648219 --dkek-shares 1</command></para>
<para>Import DKEK share</para>
<para>Import DKEK share:</para>
<para><command>sc-hsm-tool --import-dkek-share dkek-share-1.pbe</command></para>
<para>Wrap referenced key, description and certificate</para>
<para>Import DKEK share using a password split up using a (3, 5) threshold scheme for encryption:</para>
<para><command>sc-hsm-tool --import-dkek-share dkek-share-1.pbe --pwd-shares-total 3</command></para>
<para>Wrap referenced key, description and certificate:</para>
<para><command>sc-hsm-tool --wrap-key wrap-key.bin --key-reference 1 --pin 648219</command></para>
<para>Unwrap key into same or in different SmartCard-HSM with the same DKEK</para>
<para>Unwrap key into same or in different SmartCard-HSM with the same DKEK:</para>
<para><command>sc-hsm-tool --unwrap-key wrap-key.bin --key-reference 10 --pin 648219 --force</command></para>
</refsect1>

View File

@ -2,10 +2,10 @@ MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
EXTRA_DIST = Makefile.mak
# Order IS important
SUBDIRS = common scconf pkcs15init libopensc pkcs11 \
SUBDIRS = common scconf libsm pkcs15init libopensc pkcs11 \
tools tests minidriver
if ENABLE_SM
SUBDIRS += sm
SUBDIRS += smm
endif

View File

@ -2,14 +2,14 @@ TOPDIR = ..
!INCLUDE $(TOPDIR)\win32\Make.rules.mak
SUBDIRS = common scconf pkcs15init libopensc pkcs11 tools tests
SUBDIRS = common scconf libsm pkcs15init libopensc pkcs11 tools tests
!IF "$(MINIDRIVER_DEF)" == "/DENABLE_MINIDRIVER"
SUBDIRS = $(SUBDIRS) minidriver
!ENDIF
!IF "$(SM_DEF)" == "/DENABLE_SM"
SUBDIRS = $(SUBDIRS) sm
SUBDIRS = $(SUBDIRS) smm
!ENDIF
all::

View File

@ -46,7 +46,7 @@ libopensc_la_SOURCES = \
pkcs15-actalis.c pkcs15-atrust-acos.c pkcs15-tccardos.c pkcs15-piv.c \
pkcs15-esinit.c pkcs15-westcos.c pkcs15-pteid.c pkcs15-oberthur.c \
pkcs15-itacns.c pkcs15-gemsafeV1.c pkcs15-sc-hsm.c \
compression.c p15card-helper.c \
compression.c p15card-helper.c sm.c \
libopensc.exports
if WIN32
libopensc_la_SOURCES += $(top_builddir)/win32/versioninfo.rc

View File

@ -30,7 +30,7 @@ OBJECTS = \
pkcs15-actalis.obj pkcs15-atrust-acos.obj pkcs15-tccardos.obj pkcs15-piv.obj \
pkcs15-esinit.obj pkcs15-westcos.obj pkcs15-pteid.obj pkcs15-oberthur.obj \
pkcs15-itacns.obj pkcs15-gemsafeV1.obj pkcs15-sc-hsm.obj \
compression.obj p15card-helper.obj \
compression.obj p15card-helper.obj sm.obj \
$(TOPDIR)\win32\versioninfo.res
all: $(TOPDIR)\win32\versioninfo.res $(TARGET)

View File

@ -234,95 +234,6 @@ int sc_apdu_set_resp(sc_context_t *ctx, sc_apdu_t *apdu, const u8 *buf,
return SC_SUCCESS;
}
#ifdef ENABLE_SM
static const struct sc_asn1_entry c_asn1_sm_response[4] = {
{ "encryptedData", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 7, SC_ASN1_OPTIONAL, NULL, NULL },
{ "statusWord", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 0x19, 0, NULL, NULL },
{ "mac", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 0x0E, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
static int
sc_sm_parse_answer(struct sc_context *ctx, unsigned char *resp_data, size_t resp_len,
struct sm_card_response *out)
{
struct sc_asn1_entry asn1_sm_response[4];
unsigned char data[SC_MAX_APDU_BUFFER_SIZE];
size_t data_len = sizeof(data);
unsigned char status[2] = {0, 0};
size_t status_len = sizeof(status);
unsigned char mac[8];
size_t mac_len = sizeof(mac);
int r;
if (!resp_data || !resp_len || !out)
return SC_ERROR_INVALID_ARGUMENTS;
sc_copy_asn1_entry(c_asn1_sm_response, asn1_sm_response);
sc_format_asn1_entry(asn1_sm_response + 0, data, &data_len, 0);
sc_format_asn1_entry(asn1_sm_response + 1, status, &status_len, 0);
sc_format_asn1_entry(asn1_sm_response + 2, mac, &mac_len, 0);
r = sc_asn1_decode(ctx, asn1_sm_response, resp_data, resp_len, NULL, NULL);
if (r)
return r;
if (asn1_sm_response[1].flags & SC_ASN1_PRESENT) {
out->sw1 = status[0];
out->sw2 = status[1];
}
if (asn1_sm_response[2].flags & SC_ASN1_PRESENT) {
memcpy(out->mac, mac, mac_len);
out->mac_len = mac_len;
}
/* TODO: to be continued ... */
return SC_SUCCESS;
}
/** parse answer of SM protected APDU returned by APDU or by 'GET RESPONSE'
* @param card 'sc_card' smartcard object
* @param resp_data 'raw data returned by SM protected APDU
* @param resp_len 'length of raw data returned by SM protected APDU
* @param ref_rv 'status word returned by APDU or 'GET RESPONSE' (can be different from status word encoded into SM response date)
* @param apdu 'sc_apdu' object to update
* @return SC_SUCCESS on success and an error code otherwise
*/
static int
sc_sm_update_apdu_response(struct sc_card *card, unsigned char *resp_data, size_t resp_len, int ref_rv,
struct sc_apdu *apdu)
{
struct sm_card_response sm_resp;
int r;
if (!apdu)
return SC_ERROR_INVALID_ARGUMENTS;
else if (!resp_data || !resp_len)
return SC_SUCCESS;
memset(&sm_resp, 0, sizeof(sm_resp));
r = sc_sm_parse_answer(card->ctx, resp_data, resp_len, &sm_resp);
if (r)
return r;
else if (!sm_resp.sw1 && !sm_resp.sw2)
return SC_ERROR_INVALID_DATA;
else if (ref_rv != sc_check_sw(card, sm_resp.sw1, sm_resp.sw2))
return SC_ERROR_INVALID_DATA;
if (sm_resp.mac_len) {
if (sm_resp.mac_len > sizeof(apdu->mac))
return SC_ERROR_INVALID_DATA;
memcpy(apdu->mac, sm_resp.mac, sm_resp.mac_len);
apdu->mac_len = sm_resp.mac_len;
}
apdu->sw1 = sm_resp.sw1;
apdu->sw2 = sm_resp.sw2;
return SC_SUCCESS;
}
#endif
/*********************************************************************/
/* higher level APDU transfer handling functions */
@ -354,7 +265,8 @@ sc_sm_update_apdu_response(struct sc_card *card, unsigned char *resp_data, size_
* @param apdu sc_apdu_t object to check
* @return SC_SUCCESS on success and an error code otherwise
*/
static int sc_check_apdu(sc_card_t *card, const sc_apdu_t *apdu)
int
sc_check_apdu(sc_card_t *card, const sc_apdu_t *apdu)
{
if ((apdu->cse & ~SC_APDU_SHORT_MASK) == 0) {
/* length check for short APDU */
@ -441,7 +353,8 @@ error:
* APDU if one of the SC_APDU_CASE_? types is used.
* @param apdu APDU object
*/
static void sc_detect_apdu_cse(const sc_card_t *card, sc_apdu_t *apdu)
static void
sc_detect_apdu_cse(const sc_card_t *card, sc_apdu_t *apdu)
{
if (apdu->cse == SC_APDU_CASE_2 || apdu->cse == SC_APDU_CASE_3 ||
apdu->cse == SC_APDU_CASE_4) {
@ -458,48 +371,6 @@ static void sc_detect_apdu_cse(const sc_card_t *card, sc_apdu_t *apdu)
}
#ifdef ENABLE_SM
static int
sc_single_sm_transmit(struct sc_card *card, struct sc_apdu *apdu)
{
struct sc_context *ctx = card->ctx;
struct sc_apdu *sm_apdu = NULL;
int rv;
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "SM_MODE:%X", card->sm_ctx.sm_mode);
if (!card->sm_ctx.ops.get_sm_apdu || !card->sm_ctx.ops.free_sm_apdu)
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
/* get SM encoded APDU */
rv = card->sm_ctx.ops.get_sm_apdu(card, apdu, &sm_apdu);
if (rv == SC_ERROR_SM_NOT_APPLIED) {
/* SM wrap of this APDU is ignored by card driver.
* Send plain APDU to the reader driver */
rv = card->reader->ops->transmit(card->reader, apdu);
LOG_FUNC_RETURN(ctx, rv);
}
LOG_TEST_RET(ctx, rv, "get SM APDU error");
/* check if SM APDU is still valid */
rv = sc_check_apdu(card, sm_apdu);
if (rv < 0) {
card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu);
LOG_TEST_RET(ctx, rv, "cannot validate SM encoded APDU");
}
/* send APDU to the reader driver */
rv = card->reader->ops->transmit(card->reader, sm_apdu);
LOG_TEST_RET(ctx, rv, "unable to transmit APDU");
/* decode SM answer and free temporary SM related data */
rv = card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu);
LOG_FUNC_RETURN(ctx, rv);
}
#endif
static int
sc_single_transmit(struct sc_card *card, struct sc_apdu *apdu)
{
@ -514,7 +385,7 @@ sc_single_transmit(struct sc_card *card, struct sc_apdu *apdu)
apdu->cla, apdu->ins, apdu->p1, apdu->p2, apdu->datalen, apdu->data);
#ifdef ENABLE_SM
if (card->sm_ctx.sm_mode == SM_MODE_TRANSMIT)
return sc_single_sm_transmit(card, apdu);
return sc_sm_single_transmit(card, apdu);
#endif
/* send APDU to the reader driver */
@ -524,6 +395,7 @@ sc_single_transmit(struct sc_card *card, struct sc_apdu *apdu)
LOG_FUNC_RETURN(ctx, rv);
}
static int
sc_set_le_and_transmit(struct sc_card *card, struct sc_apdu *apdu, size_t olen)
{

View File

@ -1134,7 +1134,7 @@ authentic_fcp_encode(struct sc_card *card, struct sc_file *file, unsigned char *
buf[offs++] = 1;
buf[offs++] = file->type == SC_FILE_TYPE_DF ? ISO7816_FILE_TYPE_DF : ISO7816_FILE_TYPE_TRANSPARENT_EF;
buf[offs++] = ISO7816_TAG_FCP_ID;
buf[offs++] = ISO7816_TAG_FCP_FID;
buf[offs++] = 2;
buf[offs++] = (file->id >> 8) & 0xFF;
buf[offs++] = file->id & 0xFF;

View File

@ -59,6 +59,9 @@ static struct sc_atr_table cardos_atrs[] = {
{ NULL, NULL, NULL, 0, 0, NULL }
};
static unsigned int algorithm_ids_in_tokeninfo[SC_MAX_SUPPORTED_ALGORITHMS];
static unsigned int algorithm_ids_in_tokeninfo_count=0;
static int cardos_match_card(sc_card_t *card)
{
unsigned char atr[SC_MAX_ATR_SIZE];
@ -732,9 +735,8 @@ cardos_set_security_env(sc_card_t *card,
assert(card != NULL && env != NULL);
if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
|| env->key_ref_len != 1) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "No or invalid key reference\n");
if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT) || env->key_ref_len != 1) {
sc_log(card->ctx, "No or invalid key reference\n");
return SC_ERROR_INVALID_ARGUMENTS;
}
key_id = env->key_ref[0];
@ -769,7 +771,28 @@ cardos_set_security_env(sc_card_t *card,
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "Card returned error");
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, r);
do {
const struct sc_supported_algo_info* algorithm_info = env->supported_algos;
int i=0;
int algorithm_id_count = 0;
for(i=0;i<SC_MAX_SUPPORTED_ALGORITHMS;++i) {
struct sc_supported_algo_info alg = algorithm_info[i];
if(alg.operations & SC_PKCS15_ALGO_OP_COMPUTE_SIGNATURE) {
unsigned int algorithm_id = alg.algo_ref;
sc_log(card->ctx, "is signature");
sc_log(card->ctx, "Adding ID %d at index %d", algorithm_id, algorithm_id_count);
algorithm_ids_in_tokeninfo[algorithm_id_count++] = algorithm_id;
}
sc_log(card->ctx, "reference=%d, mechanism=%d, operations=%d, algo_ref=%d",
alg.reference, alg.mechanism, alg.operations, alg.algo_ref);
}
algorithm_ids_in_tokeninfo_count = algorithm_id_count;
} while (0);
LOG_FUNC_RETURN(card->ctx, r);
}
/*
@ -812,71 +835,102 @@ cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
u8 buf[SC_MAX_APDU_BUFFER_SIZE];
size_t buf_len = sizeof(buf), tmp_len = buf_len;
sc_context_t *ctx;
int do_rsa_pure_sig = 0;
int do_rsa_sig = 0;
assert(card != NULL && data != NULL && out != NULL);
assert(card != NULL && data != NULL && out != NULL);
ctx = card->ctx;
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
if (datalen > SC_MAX_APDU_BUFFER_SIZE)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
if (outlen < datalen)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_BUFFER_TOO_SMALL);
LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL);
outlen = datalen;
/* XXX As we don't know what operations are allowed with a
* certain key, let's try RSA_PURE etc. and see which operation
* succeeds (this is not really beautiful, but currently the
* only way I see) -- Nils
/* There are two ways to create a signature, depending on the way,
* the key was created: RSA_SIG and RSA_PURE_SIG.
* We can use the following reasoning, to determine the correct operation:
* 1. We check for several caps flags (as set in card->caps), to pervent generating
* invalid signatures with duplicated hash prefixes with some cards
* 2. Use the information from AlgorithmInfo of the TokenInfo file.
* This information is parsed in set_security_env and stored in a static variable.
* The problem is, that that information is only available for the whole token and not
for a specific key, so if both operations are present, we can only do trial and error
*
* We also check for several caps flags here to pervent generating
* invalid signatures with duplicated hash prefixes with some cards
* The Algorithm IDs for RSA_SIG are 0x86 and 0x88, those for RSA_PURE_SIG 0x8c and 0x8a
* (According to http://www.opensc-project.org/pipermail/opensc-devel/2010-September/014912.html
* and www.crysys.hu/infsec/M40_Manual_E_2001_10.pdf)
*/
if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED)
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Forcing RAW_HASH_STRIPPED\n");
if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH)
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Forcing RAW_HASH\n");
if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED){
sc_log(ctx, "Forcing RAW_HASH_STRIPPED");
do_rsa_sig = 1;
}
else if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH){
sc_log(ctx, "Forcing RAW_HASH");
do_rsa_sig = 1;
}
else {
//check the the algorithmIDs from the AlgorithmInfo
int i;
for(i=0; i<algorithm_ids_in_tokeninfo_count;++i){
unsigned int id = algorithm_ids_in_tokeninfo[i];
if(id == 0x86 || id == 0x88)
do_rsa_sig = 1;
else if(id == 0x8C || id == 0x8A)
do_rsa_pure_sig = 1;
}
}
if (!(card->caps & (SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED | SC_CARD_CAP_ONLY_RAW_HASH))) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying RSA_PURE_SIG (padded DigestInfo)\n");
//check if any operation was selected
if(do_rsa_sig == 0 && do_rsa_pure_sig == 0) {
//no operation selected. we just have to try both, for the lack of any better reasoning
sc_log(ctx, "I was unable to determine, wether this key can be used with RSA_SIG or RSA_PURE_SIG. I will just try both.");
do_rsa_sig = 1;
do_rsa_pure_sig = 1;
}
if(do_rsa_pure_sig == 1){
sc_log(ctx, "trying RSA_PURE_SIG (padded DigestInfo)");
r = do_compute_signature(card, data, datalen, out, outlen);
if (r >= SC_SUCCESS)
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
}
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying RSA_SIG (just the DigestInfo)\n");
/* remove padding: first try pkcs1 bt01 padding */
r = sc_pkcs1_strip_01_padding(data, datalen, buf, &tmp_len);
if (r != SC_SUCCESS) {
const u8 *p = data;
/* no pkcs1 bt01 padding => let's try zero padding
* This can only work if the data tbs doesn't have a
* leading 0 byte. */
tmp_len = buf_len;
while (*p == 0 && tmp_len != 0) {
++p;
--tmp_len;
LOG_FUNC_RETURN(ctx, r);
}
if(do_rsa_sig == 1){
sc_log(ctx, "trying RSA_SIG (just the DigestInfo)");
/* remove padding: first try pkcs1 bt01 padding */
r = sc_pkcs1_strip_01_padding(data, datalen, buf, &tmp_len);
if (r != SC_SUCCESS) {
const u8 *p = data;
/* no pkcs1 bt01 padding => let's try zero padding
* This can only work if the data tbs doesn't have a
* leading 0 byte. */
tmp_len = buf_len;
while (*p == 0 && tmp_len != 0) {
++p;
--tmp_len;
}
memcpy(buf, p, tmp_len);
}
memcpy(buf, p, tmp_len);
if (!(card->caps & (SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED | SC_CARD_CAP_ONLY_RAW_HASH)) || card->caps & SC_CARD_CAP_ONLY_RAW_HASH ) {
sc_log(ctx, "trying to sign raw hash value with prefix");
r = do_compute_signature(card, buf, tmp_len, out, outlen);
if (r >= SC_SUCCESS)
LOG_FUNC_RETURN(ctx, r);
}
if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH) {
sc_log(ctx, "Failed to sign raw hash value with prefix when forcing");
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
}
sc_log(ctx, "trying to sign stripped raw hash value (card is responsible for prefix)");
r = sc_pkcs1_strip_digest_info_prefix(NULL,buf,tmp_len,buf,&buf_len);
if (r != SC_SUCCESS)
LOG_FUNC_RETURN(ctx, r);
return do_compute_signature(card, buf, buf_len, out, outlen);
}
if (!(card->caps & (SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED | SC_CARD_CAP_ONLY_RAW_HASH)) || card->caps & SC_CARD_CAP_ONLY_RAW_HASH ) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying to sign raw hash value with prefix\n");
r = do_compute_signature(card, buf, tmp_len, out, outlen);
if (r >= SC_SUCCESS)
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
}
if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Failed to sign raw hash value with prefix when forcing\n");
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
}
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "trying to sign stripped raw hash value (card is responsible for prefix)\n");
r = sc_pkcs1_strip_digest_info_prefix(NULL,buf,tmp_len,buf,&buf_len);
if (r != SC_SUCCESS)
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
return do_compute_signature(card, buf, buf_len, out, outlen);
}
static int

View File

@ -117,8 +117,8 @@ openssl_enc(const EVP_CIPHER * cipher, const unsigned char *key, const unsigned
memcpy(iv_tmp, iv, EVP_MAX_IV_LENGTH);
EVP_CIPHER_CTX_init(&ctx);
EVP_CIPHER_CTX_set_padding(&ctx, 0);
EVP_EncryptInit_ex(&ctx, cipher, NULL, key, iv_tmp);
EVP_CIPHER_CTX_set_padding(&ctx, 0);
if (!EVP_EncryptUpdate(&ctx, output, &outl, input, length))
goto out;
@ -146,8 +146,8 @@ openssl_dec(const EVP_CIPHER * cipher, const unsigned char *key, const unsigned
memcpy(iv_tmp, iv, EVP_MAX_IV_LENGTH);
EVP_CIPHER_CTX_init(&ctx);
EVP_CIPHER_CTX_set_padding(&ctx, 0);
EVP_DecryptInit_ex(&ctx, cipher, NULL, key, iv_tmp);
EVP_CIPHER_CTX_set_padding(&ctx, 0);
if (!EVP_DecryptUpdate(&ctx, output, &outl, input, length))
goto out;
@ -1003,10 +1003,10 @@ epass2003_init(struct sc_card *card)
flags = SC_ALGORITHM_ONBOARD_KEY_GEN | SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE;
_sc_card_add_rsa_alg(card, 512, flags, 0x10001);
_sc_card_add_rsa_alg(card, 768, flags, 0x10001);
_sc_card_add_rsa_alg(card, 1024, flags, 0x10001);
_sc_card_add_rsa_alg(card, 2048, flags, 0x10001);
_sc_card_add_rsa_alg(card, 512, flags, 0);
_sc_card_add_rsa_alg(card, 768, flags, 0);
_sc_card_add_rsa_alg(card, 1024, flags, 0);
_sc_card_add_rsa_alg(card, 2048, flags, 0);
card->caps = SC_CARD_CAP_RNG | SC_CARD_CAP_APDU_EXT;
@ -1858,7 +1858,6 @@ epass2003_delete_file(struct sc_card *card, const sc_path_t * path)
LOG_FUNC_RETURN(card->ctx, r);
}
#if 0
static int
epass2003_list_files(struct sc_card *card, unsigned char *buf, size_t buflen)
{
@ -1867,9 +1866,9 @@ epass2003_list_files(struct sc_card *card, unsigned char *buf, size_t buflen)
int r;
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x34, 0x00, 0x00);
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x34, 0x00, 0x00);
apdu.cla = 0x80;
apdu.le = 0x40;
apdu.le = 0;
apdu.resplen = sizeof(rbuf);
apdu.resp = rbuf;
@ -1887,7 +1886,6 @@ epass2003_list_files(struct sc_card *card, unsigned char *buf, size_t buflen)
LOG_FUNC_RETURN(card->ctx, buflen);
}
#endif
static int
@ -2376,7 +2374,7 @@ static struct sc_card_driver *sc_get_driver(void)
epass2003_ops.compute_signature = epass2003_decipher;
epass2003_ops.create_file = epass2003_create_file;
epass2003_ops.delete_file = epass2003_delete_file;
/* epass2003_ops.list_files = epass2003_list_files; */
epass2003_ops.list_files = epass2003_list_files;
epass2003_ops.card_ctl = epass2003_card_ctl;
epass2003_ops.process_fci = epass2003_process_fci;
epass2003_ops.construct_fci = epass2003_construct_fci;

View File

@ -31,9 +31,6 @@
#include "asn1.h"
#include "cardctl.h"
/* Portugal eID uses 1024 bit keys */
#define PTEID_RSA_KEYSIZE 128
#define DRVDATA(card) ((struct ias_priv_data *) ((card)->drv_data))
static struct sc_card_operations ias_ops;
@ -309,14 +306,17 @@ static int ias_set_security_env(sc_card_t *card,
return r;
}
static int ias_compute_signature(sc_card_t *card, const u8 * data,
size_t data_len, u8 * out, size_t outlen)
static int ias_compute_signature(sc_card_t *card, const u8 *data,
size_t data_len, u8 *out, size_t outlen)
{
int r;
size_t len = 0;
sc_apdu_t apdu;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
sc_context_t *ctx = card->ctx;
sc_apdu_t apdu;
size_t len;
/*
** XXX: Ensure sufficient space exists for the card's response
** as the caller's buffer size may not be sufficient
*/
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
sc_context_t *ctx = card->ctx;
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
@ -324,28 +324,22 @@ static int ias_compute_signature(sc_card_t *card, const u8 * data,
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "error: input data too long: %lu bytes\n", data_len);
return SC_ERROR_INVALID_ARGUMENTS;
}
/* Send the data */
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x88, 0x02, 0x00);
memcpy(sbuf, data, data_len);
apdu.data = sbuf;
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x02, 0x00);
apdu.data = (u8 *) data;
apdu.lc = data_len;
apdu.datalen = data_len;
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
apdu.le = 256;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
LOG_TEST_RET(card->ctx, sc_transmit_apdu(card, &apdu), "APDU transmit failed");
LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "INTERNAL AUTHENTICATE failed");
/* Get the result */
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
len = card->type == SC_CARD_TYPE_IAS_PTEID ? PTEID_RSA_KEYSIZE : outlen;
r = iso_ops->get_response(card, &len, out);
if (r == 0)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, len);
else
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
}
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
len = apdu.resplen > outlen ? outlen : apdu.resplen;
memcpy(out, apdu.resp, len);
LOG_FUNC_RETURN(card->ctx, apdu.resplen);
}
static int ias_select_file(sc_card_t *card, const sc_path_t *in_path,

View File

@ -1,7 +1,7 @@
/*
* card-javacard.c: Recognize known blank JavaCards
*
* Copyright (C) 2010 Martin Paljak <martin@paljak.pri.ee>
* Copyright (C) 2010 Martin Paljak <martin@martinpaljak.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@ -1,7 +1,7 @@
/*
* card-mcrd.c: Support for MICARDO cards
*
* Copyright (C) 2004 Martin Paljak <martin@paljak.pri.ee>
* Copyright (C) 2004 Martin Paljak <martin@martinpaljak.net>
* Copyright (C) 2004 Priit Randla <priit.randla@eyp.ee>
* Copyright (C) 2003 Marie Fischer <marie@vtl.ee>
* Copyright (C) 2001 Juha Yrjölä <juha.yrjola@iki.fi>

View File

@ -174,7 +174,7 @@ static int sc_hsm_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
if (data->cmd == SC_PIN_CMD_GET_INFO) {
return sc_hsm_pin_info(card, data, tries_left);
}
if (data->pin_reference == 0x88) {
if ((data->cmd == SC_PIN_CMD_VERIFY) && (data->pin_reference == 0x88)) {
// Save SO PIN for later use in init pin
memcpy(priv->initpw, data->pin1.data, sizeof(priv->initpw));
return SC_SUCCESS;
@ -557,7 +557,7 @@ static int sc_hsm_decipher(sc_card_t *card, const u8 * crgram, size_t crgram_len
apdu.resplen = sizeof(rbuf);
apdu.le = 256;
apdu.data = crgram;
apdu.data = (u8 *)crgram;
apdu.lc = crgram_len;
apdu.datalen = crgram_len;
@ -718,7 +718,7 @@ static int sc_hsm_wrap_key(sc_card_t *card, sc_cardctl_sc_hsm_wrapped_key_t *par
{
sc_context_t *ctx = card->ctx;
sc_apdu_t apdu;
u8 data[SC_MAX_EXT_APDU_BUFFER_SIZE];
u8 data[MAX_EXT_APDU_LENGTH];
int r;
LOG_FUNC_CALLED(card->ctx);
@ -736,10 +736,17 @@ static int sc_hsm_wrap_key(sc_card_t *card, sc_cardctl_sc_hsm_wrapped_key_t *par
LOG_TEST_RET(ctx, r, "Check SW error");
params->wrapped_key_length = apdu.resplen;
params->wrapped_key = malloc(apdu.resplen);
if (params->wrapped_key == NULL) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
params->wrapped_key_length = apdu.resplen;
params->wrapped_key = malloc(apdu.resplen);
if (params->wrapped_key == NULL) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
} else {
if (apdu.resplen > params->wrapped_key_length) {
LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL);
}
params->wrapped_key_length = apdu.resplen;
}
memcpy(params->wrapped_key, data, apdu.resplen);
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);

View File

@ -61,6 +61,55 @@ void sc_format_apdu(sc_card_t *card, sc_apdu_t *apdu,
apdu->p2 = (u8) p2;
}
struct sc_apdu *
sc_allocate_apdu(struct sc_apdu *copy_from, unsigned flags)
{
struct sc_apdu *apdu = NULL;
assert(copy_from != NULL);
apdu = (struct sc_apdu *)malloc(sizeof(struct sc_apdu));
if (!copy_from || !apdu)
return apdu;
memcpy(apdu, copy_from, sizeof(struct sc_apdu));
apdu->data = apdu->resp = NULL;
apdu->next = NULL;
apdu->datalen = apdu->resplen = 0;
apdu->allocation_flags = SC_APDU_ALLOCATE_FLAG;
if ((flags & SC_APDU_ALLOCATE_FLAG_DATA) && copy_from->data && copy_from->datalen) {
apdu->data = malloc(copy_from->datalen);
if (!apdu->data)
return NULL;
memcpy(apdu->data, copy_from->data, copy_from->datalen);
apdu->datalen = copy_from->datalen;
apdu->allocation_flags |= SC_APDU_ALLOCATE_FLAG_DATA;
}
if ((flags & SC_APDU_ALLOCATE_FLAG_RESP) && copy_from->resp && copy_from->resplen) {
apdu->resp = malloc(copy_from->resplen);
if (!apdu->resp)
return NULL;
memcpy(apdu->resp, copy_from->resp, copy_from->resplen);
apdu->resplen = copy_from->resplen;
apdu->allocation_flags |= SC_APDU_ALLOCATE_FLAG_RESP;
}
return apdu;
}
void
sc_free_apdu(struct sc_apdu *apdu)
{
if (!apdu)
return;
if (apdu->allocation_flags & SC_APDU_ALLOCATE_FLAG_DATA)
free (apdu->data);
if (apdu->allocation_flags & SC_APDU_ALLOCATE_FLAG_RESP)
free (apdu->resp);
if (apdu->allocation_flags & SC_APDU_ALLOCATE_FLAG)
free (apdu);
}
static sc_card_t * sc_card_new(sc_context_t *ctx)
{
sc_card_t *card;
@ -968,32 +1017,40 @@ int _sc_add_atr(sc_context_t *ctx, struct sc_card_driver *driver, struct sc_atr_
if (!map)
return SC_ERROR_OUT_OF_MEMORY;
driver->atr_map = map;
dst = &driver->atr_map[driver->natrs++];
memset(dst, 0, sizeof(*dst));
memset(&driver->atr_map[driver->natrs], 0, sizeof(struct sc_atr_table));
dst->atr = strdup(src->atr);
if (!dst->atr)
return SC_ERROR_OUT_OF_MEMORY;
if (src->atrmask) {
dst->atrmask = strdup(src->atrmask);
if (!dst->atrmask)
return SC_ERROR_OUT_OF_MEMORY;
} else {
}
else {
dst->atrmask = NULL;
}
if (src->name) {
dst->name = strdup(src->name);
if (!dst->name)
return SC_ERROR_OUT_OF_MEMORY;
} else {
}
else {
dst->name = NULL;
}
dst->type = src->type;
dst->flags = src->flags;
dst->card_atr = src->card_atr;
return SC_SUCCESS;
}
int _sc_free_atr(sc_context_t *ctx, struct sc_card_driver *driver)
{
unsigned int i;
@ -1130,7 +1187,7 @@ sc_card_sm_load(struct sc_card *card, const char *module_path, const char *in_mo
}
if (!module)
return SC_ERROR_MEMORY_FAILURE;
return SC_ERROR_OUT_OF_MEMORY;
sc_log(ctx, "try to load SM module '%s'", module);
do {
@ -1197,6 +1254,7 @@ sc_card_sm_check(struct sc_card *card)
int rv, ii;
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
sc_log(ctx, "card->sm_ctx.ops.open %p", card->sm_ctx.ops.open);
/* get the name of card specific SM configuration section */
atrblock = _sc_match_atr_block(ctx, card->driver, &card->atr);

View File

@ -120,7 +120,6 @@ const char *sc_strerror(int error)
};
const int p15i_base = -SC_ERROR_PKCS15INIT;
const int sm_base = -SC_ERROR_SM;
const char *sm_errors[] = {
"Generic Secure Messaging error",
"Data enciphering error",
@ -131,9 +130,12 @@ const char *sc_strerror(int error)
"Cannot authenticate card",
"Random generation error",
"Secure messaging keyset not found",
"IFD data missing"
"IFD data missing",
"SM not applied",
"SM session already active",
"Invalid checksum"
};
const int sm_base = -SC_ERROR_SM;
const char *misc_errors[] = {
"Unknown error",

View File

@ -110,18 +110,19 @@ extern "C" {
#define SC_ERROR_FILE_TOO_SMALL -1510
/* Related to secure messaging */
#define SC_ERROR_SM -1600
#define SC_ERROR_SM_ENCRYPT_FAILED -1601
#define SC_ERROR_SM_INVALID_LEVEL -1602
#define SC_ERROR_SM_NO_SESSION_KEYS -1603
#define SC_ERROR_SM_INVALID_SESSION_KEY -1604
#define SC_ERROR_SM_NOT_INITIALIZED -1605
#define SC_ERROR_SM_AUTHENTICATION_FAILED -1606
#define SC_ERROR_SM_RAND_FAILED -1607
#define SC_ERROR_SM_KEYSET_NOT_FOUND -1608
#define SC_ERROR_SM_IFD_DATA_MISSING -1609
#define SC_ERROR_SM_NOT_APPLIED -1610
#define SC_ERROR_SM -1600
#define SC_ERROR_SM_ENCRYPT_FAILED -1601
#define SC_ERROR_SM_INVALID_LEVEL -1602
#define SC_ERROR_SM_NO_SESSION_KEYS -1603
#define SC_ERROR_SM_INVALID_SESSION_KEY -1604
#define SC_ERROR_SM_NOT_INITIALIZED -1605
#define SC_ERROR_SM_AUTHENTICATION_FAILED -1606
#define SC_ERROR_SM_RAND_FAILED -1607
#define SC_ERROR_SM_KEYSET_NOT_FOUND -1608
#define SC_ERROR_SM_IFD_DATA_MISSING -1609
#define SC_ERROR_SM_NOT_APPLIED -1610
#define SC_ERROR_SM_SESSION_ALREADY_ACTIVE -1611
#define SC_ERROR_SM_INVALID_CHECKSUM -1612
/* Errors that do not fit the categories above */
#define SC_ERROR_UNKNOWN -1900

View File

@ -763,7 +763,7 @@ iasecc_sdo_allocate_and_parse(struct sc_card *card, unsigned char *data, size_t
sdo = calloc(1, sizeof(struct iasecc_sdo));
if (!sdo)
return SC_ERROR_MEMORY_FAILURE;
return SC_ERROR_OUT_OF_MEMORY;
sdo->sdo_class = *(data + 1) & 0x7F;
sdo->sdo_ref = *(data + 2) & 0x3F;
@ -823,7 +823,7 @@ iasecc_update_blob(struct sc_context *ctx, struct iasecc_extended_tlv *tlv,
pp = realloc(*blob, *blob_size + sz);
if (!pp)
LOG_FUNC_RETURN(ctx, SC_ERROR_MEMORY_FAILURE);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
if (tlv->tag > 0xFF)
*(pp + *blob_size + offs++) = (tlv->tag >> 8) & 0xFF;

View File

@ -30,14 +30,14 @@
#include "iso7816.h"
static const struct sc_card_error iso7816_errors[] = {
{ 0x6200, SC_ERROR_MEMORY_FAILURE, "State of non-volatile memory unchanged" },
{ 0x6200, SC_ERROR_CARD_CMD_FAILED, "Warning: no information given, non-volatile memory is unchanged" },
{ 0x6281, SC_ERROR_CORRUPTED_DATA, "Part of returned data may be corrupted" },
{ 0x6282, SC_ERROR_FILE_END_REACHED, "End of file/record reached before reading Le bytes" },
{ 0x6283, SC_ERROR_CARD_CMD_FAILED, "Selected file invalidated" },
{ 0x6284, SC_ERROR_CARD_CMD_FAILED, "FCI not formatted according to ISO 7816-4" },
{ 0x6300, SC_ERROR_MEMORY_FAILURE, "State of non-volatile memory changed" },
{ 0x6381, SC_ERROR_CARD_CMD_FAILED, "File filled up by last write" },
{ 0x6300, SC_ERROR_CARD_CMD_FAILED, "Warning: no information given, non-volatile memory has changed" },
{ 0x6381, SC_ERROR_CARD_CMD_FAILED, "Warning: file filled up by last write" },
{ 0x6581, SC_ERROR_MEMORY_FAILURE, "Memory failure" },
@ -67,57 +67,58 @@ static const struct sc_card_error iso7816_errors[] = {
{ 0x6A86, SC_ERROR_INCORRECT_PARAMETERS,"Incorrect parameters P1-P2" },
{ 0x6A87, SC_ERROR_INCORRECT_PARAMETERS,"Lc inconsistent with P1-P2" },
{ 0x6A88, SC_ERROR_DATA_OBJECT_NOT_FOUND,"Referenced data not found" },
{ 0x6A89, SC_ERROR_FILE_ALREADY_EXISTS, "File already exists"},
{ 0x6A8A, SC_ERROR_FILE_ALREADY_EXISTS, "DF name already exists"},
{ 0x6B00, SC_ERROR_INCORRECT_PARAMETERS,"Wrong parameter(s) P1-P2" },
{ 0x6D00, SC_ERROR_INS_NOT_SUPPORTED, "Instruction code not supported or invalid" },
{ 0x6E00, SC_ERROR_CLASS_NOT_SUPPORTED, "Class not supported" },
{ 0x6F00, SC_ERROR_CARD_CMD_FAILED, "No precise diagnosis" },
/* Possibly TCOS / Micardo specific errors */
{ 0x6600, SC_ERROR_INCORRECT_PARAMETERS, "Error setting the security env"},
{ 0x66F0, SC_ERROR_INCORRECT_PARAMETERS, "No space left for padding"},
{ 0x69F0, SC_ERROR_NOT_ALLOWED, "Command not allowed"},
{ 0x6A89, SC_ERROR_FILE_ALREADY_EXISTS, "Files exists"},
{ 0x6A8A, SC_ERROR_FILE_ALREADY_EXISTS, "Application exists"},
};
static int iso7816_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2)
static int
iso7816_check_sw(struct sc_card *card, unsigned int sw1, unsigned int sw2)
{
const int err_count = sizeof(iso7816_errors)/sizeof(iso7816_errors[0]);
int i;
/* Handle special cases here */
if (sw1 == 0x6C) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Wrong length; correct length is %d", sw2);
sc_log(card->ctx, "Wrong length; correct length is %d", sw2);
return SC_ERROR_WRONG_LENGTH;
}
if (sw1 == 0x90)
return SC_SUCCESS;
if (sw1 == 0x63U && (sw2 & ~0x0fU) == 0xc0U ) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Verification failed (remaining tries: %d)",
(sw2 & 0x0f));
sc_log(card->ctx, "Verification failed (remaining tries: %d)", (sw2 & 0x0f));
return SC_ERROR_PIN_CODE_INCORRECT;
}
for (i = 0; i < err_count; i++)
for (i = 0; i < err_count; i++) {
if (iso7816_errors[i].SWs == ((sw1 << 8) | sw2)) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s", iso7816_errors[i].errorstr);
sc_log(card->ctx, "%s", iso7816_errors[i].errorstr);
return iso7816_errors[i].errorno;
}
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unknown SWs; SW1=%02X, SW2=%02X", sw1, sw2);
}
sc_log(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X", sw1, sw2);
return SC_ERROR_CARD_CMD_FAILED;
}
static int iso7816_read_binary(sc_card_t *card,
unsigned int idx, u8 *buf, size_t count,
unsigned long flags)
static int
iso7816_read_binary(struct sc_card *card, unsigned int idx, u8 *buf, size_t count, unsigned long flags)
{
sc_context_t *ctx = card->ctx;
sc_apdu_t apdu;
struct sc_context *ctx = card->ctx;
struct sc_apdu apdu;
u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
int r;
if (idx > 0x7fff) {
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "invalid EF offset: 0x%X > 0x7FFF", idx);
sc_log(ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
return SC_ERROR_OFFSET_TOO_LARGE;
}
@ -128,33 +129,34 @@ static int iso7816_read_binary(sc_card_t *card,
apdu.resp = recvbuf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
LOG_TEST_RET(ctx, r, "APDU transmit failed");
if (apdu.resplen == 0)
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
LOG_FUNC_RETURN(ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
memcpy(buf, recvbuf, apdu.resplen);
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (r == SC_ERROR_FILE_END_REACHED)
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, apdu.resplen);
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, r, "Check SW error");
LOG_FUNC_RETURN(ctx, apdu.resplen);
LOG_TEST_RET(ctx, r, "Check SW error");
if (apdu.resplen < count) {
r = iso7816_read_binary(card, idx + apdu.resplen, buf + apdu.resplen, count - apdu.resplen, flags);
/* Ignore all but 'corrupted data' errors */
if (r == SC_ERROR_CORRUPTED_DATA)
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_CORRUPTED_DATA);
LOG_FUNC_RETURN(ctx, SC_ERROR_CORRUPTED_DATA);
else if (r > 0)
apdu.resplen += r;
}
SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, apdu.resplen);
LOG_FUNC_RETURN(ctx, apdu.resplen);
}
static int iso7816_read_record(sc_card_t *card,
unsigned int rec_nr, u8 *buf, size_t count,
unsigned long flags)
static int
iso7816_read_record(struct sc_card *card,
unsigned int rec_nr, u8 *buf, size_t count, unsigned long flags)
{
sc_apdu_t apdu;
struct sc_apdu apdu;
u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
int r;
@ -162,110 +164,119 @@ static int iso7816_read_record(sc_card_t *card,
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
if (flags & SC_RECORD_BY_REC_NR)
apdu.p2 |= 0x04;
apdu.le = count;
apdu.resplen = count;
apdu.resp = recvbuf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.resplen == 0)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
memcpy(buf, recvbuf, apdu.resplen);
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, apdu.resplen);
LOG_FUNC_RETURN(card->ctx, apdu.resplen);
}
static int iso7816_write_record(sc_card_t *card, unsigned int rec_nr,
const u8 *buf, size_t count,
unsigned long flags)
static int
iso7816_write_record(struct sc_card *card, unsigned int rec_nr,
const u8 *buf, size_t count, unsigned long flags)
{
sc_apdu_t apdu;
struct sc_apdu apdu;
int r;
if (count > 256) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Trying to send too many bytes");
sc_log(card->ctx, "Trying to send too many bytes");
return SC_ERROR_INVALID_ARGUMENTS;
}
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD2, rec_nr, 0);
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
if (flags & SC_RECORD_BY_REC_NR)
apdu.p2 |= 0x04;
apdu.lc = count;
apdu.datalen = count;
apdu.data = buf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sc_check_sw(card, apdu.sw1, apdu.sw2),
"Card returned error");
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, count);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, count);
}
static int iso7816_append_record(sc_card_t *card,
const u8 *buf, size_t count,
unsigned long flags)
static int
iso7816_append_record(struct sc_card *card,
const u8 *buf, size_t count, unsigned long flags)
{
sc_apdu_t apdu;
struct sc_apdu apdu;
int r;
if (count > 256) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Trying to send too many bytes");
sc_log(card->ctx, "Trying to send too many bytes");
return SC_ERROR_INVALID_ARGUMENTS;
}
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE2, 0, 0);
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
apdu.lc = count;
apdu.datalen = count;
apdu.data = buf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sc_check_sw(card, apdu.sw1, apdu.sw2),
"Card returned error");
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, count);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, count);
}
static int iso7816_update_record(sc_card_t *card, unsigned int rec_nr,
const u8 *buf, size_t count,
unsigned long flags)
static int
iso7816_update_record(struct sc_card *card, unsigned int rec_nr,
const u8 *buf, size_t count, unsigned long flags)
{
sc_apdu_t apdu;
struct sc_apdu apdu;
int r;
if (count > 256) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Trying to send too many bytes");
sc_log(card->ctx, "Trying to send too many bytes");
return SC_ERROR_INVALID_ARGUMENTS;
}
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDC, rec_nr, 0);
apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
if (flags & SC_RECORD_BY_REC_NR)
apdu.p2 |= 0x04;
apdu.lc = count;
apdu.datalen = count;
apdu.data = buf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sc_check_sw(card, apdu.sw1, apdu.sw2),
"Card returned error");
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, count);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, count);
}
static int iso7816_write_binary(sc_card_t *card,
unsigned int idx, const u8 *buf,
size_t count, unsigned long flags)
static int
iso7816_write_binary(struct sc_card *card,
unsigned int idx, const u8 *buf, size_t count, unsigned long flags)
{
sc_apdu_t apdu;
struct sc_apdu apdu;
int r;
assert(count <= (card->max_send_size > 0 ? card->max_send_size : 255));
if (idx > 0x7fff) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "invalid EF offset: 0x%X > 0x7FFF", idx);
sc_log(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
return SC_ERROR_OFFSET_TOO_LARGE;
}
@ -276,37 +287,39 @@ static int iso7816_write_binary(sc_card_t *card,
apdu.data = buf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sc_check_sw(card, apdu.sw1, apdu.sw2),
"Card returned error");
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, count);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, count);
}
static int iso7816_update_binary(sc_card_t *card,
unsigned int idx, const u8 *buf,
size_t count, unsigned long flags)
static int
iso7816_update_binary(struct sc_card *card,
unsigned int idx, const u8 *buf, size_t count, unsigned long flags)
{
sc_apdu_t apdu;
struct sc_apdu apdu;
int r;
assert(count <= (card->max_send_size > 0 ? card->max_send_size : 255));
if (idx > 0x7fff) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "invalid EF offset: 0x%X > 0x7FFF", idx);
sc_log(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
return SC_ERROR_OFFSET_TOO_LARGE;
}
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6,
(idx >> 8) & 0x7F, idx & 0xFF);
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6, (idx >> 8) & 0x7F, idx & 0xFF);
apdu.lc = count;
apdu.datalen = count;
apdu.data = buf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, sc_check_sw(card, apdu.sw1, apdu.sw2),
"Card returned error");
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, count);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, count);
}
@ -324,6 +337,7 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
file->id = (tag[0] << 8) | tag[1];
sc_log(ctx, " file identifier: 0x%02X%02X", tag[0], tag[1]);
}
tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
if (tag != NULL && taglen > 0 && taglen < 3) {
file->size = tag[0];
@ -335,10 +349,12 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
tag = sc_asn1_find_tag(ctx, p, len, 0x81, &taglen);
if (tag != NULL && taglen >= 2) {
int bytes = (tag[0] << 8) + tag[1];
sc_log(ctx, " bytes in file: %d", bytes);
file->size = bytes;
}
}
tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
if (tag != NULL) {
if (taglen > 0) {
@ -369,9 +385,11 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
sc_log(ctx, " EF structure: %d", byte & 0x07);
}
}
tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen);
if (tag != NULL && taglen > 0 && taglen <= 16) {
char tbuf[128];
memcpy(file->name, tag, taglen);
file->namelen = taglen;
@ -404,8 +422,8 @@ iso7816_process_fci(struct sc_card *card, struct sc_file *file,
else if (tag[0] == 0x06 || tag[0] == 0x04)
file->status = SC_FILE_STATUS_INVALIDATED;
}
file->magic = SC_FILE_MAGIC;
file->magic = SC_FILE_MAGIC;
return SC_SUCCESS;
}
@ -499,7 +517,7 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct
case ISO7816_TAG_FCP:
file = sc_file_new();
if (file == NULL)
LOG_FUNC_RETURN(ctx,SC_ERROR_OUT_OF_MEMORY);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
file->path = *in_path;
if (card->ops->process_fci == NULL) {
sc_file_free(file);
@ -514,40 +532,44 @@ iso7816_select_file(struct sc_card *card, const struct sc_path *in_path, struct
default:
LOG_FUNC_RETURN(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED);
}
return SC_SUCCESS;
}
static int iso7816_get_challenge(sc_card_t *card, u8 *rnd, size_t len)
static int
iso7816_get_challenge(struct sc_card *card, u8 *rnd, size_t len)
{
int r;
sc_apdu_t apdu;
struct sc_apdu apdu;
u8 buf[10];
if (!rnd && len)
return SC_ERROR_INVALID_ARGUMENTS;
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT,
0x84, 0x00, 0x00);
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x84, 0x00, 0x00);
apdu.le = 8;
apdu.resp = buf;
apdu.resplen = 8; /* include SW's */
while (len > 0) {
size_t n = len > 8 ? 8 : len;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.resplen != 8)
return sc_check_sw(card, apdu.sw1, apdu.sw2);
memcpy(rnd, apdu.resp, n);
len -= n;
rnd += n;
}
}
return 0;
}
static int iso7816_construct_fci(sc_card_t *card, const sc_file_t *file,
u8 *out, size_t *outlen)
static int
iso7816_construct_fci(struct sc_card *card, const sc_file_t *file,
u8 *out, size_t *outlen)
{
u8 *p = out;
u8 buf[64];
@ -556,7 +578,7 @@ static int iso7816_construct_fci(sc_card_t *card, const sc_file_t *file,
return SC_ERROR_BUFFER_TOO_SMALL;
*p++ = 0x6F;
p++;
buf[0] = (file->size >> 8) & 0xFF;
buf[1] = file->size & 0xFF;
sc_asn1_put_tag(0x81, buf, 2, p, *outlen - (p - out), &p);
@ -604,33 +626,40 @@ static int iso7816_construct_fci(sc_card_t *card, const sc_file_t *file,
return 0;
}
static int iso7816_create_file(sc_card_t *card, sc_file_t *file)
static int
iso7816_create_file(struct sc_card *card, sc_file_t *file)
{
int r;
size_t len;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
sc_apdu_t apdu;
struct sc_apdu apdu;
len = SC_MAX_APDU_BUFFER_SIZE;
if (card->ops->construct_fci == NULL)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
r = card->ops->construct_fci(card, file, sbuf, &len);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "construct_fci() failed");
LOG_TEST_RET(card->ctx, r, "construct_fci() failed");
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
apdu.lc = len;
apdu.datalen = len;
apdu.data = sbuf;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
return sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
return r;
}
static int iso7816_get_response(sc_card_t *card, size_t *count, u8 *buf)
static int
iso7816_get_response(struct sc_card *card, size_t *count, u8 *buf)
{
sc_apdu_t apdu;
struct sc_apdu apdu;
int r;
size_t rlen;
@ -648,9 +677,9 @@ static int iso7816_get_response(sc_card_t *card, size_t *count, u8 *buf)
apdu.flags |= SC_APDU_FLAGS_NO_GET_RESP;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.resplen == 0)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
*count = apdu.resplen;
@ -666,15 +695,17 @@ static int iso7816_get_response(sc_card_t *card, size_t *count, u8 *buf)
return r;
}
static int iso7816_delete_file(sc_card_t *card, const sc_path_t *path)
static int
iso7816_delete_file(struct sc_card *card, const sc_path_t *path)
{
int r;
u8 sbuf[2];
sc_apdu_t apdu;
struct sc_apdu apdu;
SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
if (path->type != SC_PATH_TYPE_FILE_ID || (path->len != 0 && path->len != 2)) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "File type has to be SC_PATH_TYPE_FILE_ID");
sc_log(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID");
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_INVALID_ARGUMENTS);
}
@ -686,19 +717,25 @@ static int iso7816_delete_file(sc_card_t *card, const sc_path_t *path)
apdu.datalen = 2;
apdu.data = sbuf;
}
else /* No file ID given: means currently selected file */
else {
/* No file ID given: means currently selected file */
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xE4, 0x00, 0x00);
}
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
return sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
return r;
}
static int iso7816_set_security_env(sc_card_t *card,
const sc_security_env_t *env,
int se_num)
static int
iso7816_set_security_env(struct sc_card *card,
const struct sc_security_env *env, int se_num)
{
sc_apdu_t apdu;
struct sc_apdu apdu;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
u8 *p;
int r, locked = 0;
@ -744,20 +781,18 @@ static int iso7816_set_security_env(sc_card_t *card,
apdu.data = sbuf;
if (se_num > 0) {
r = sc_lock(card);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "sc_lock() failed");
LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
locked = 1;
}
if (apdu.datalen != 0) {
r = sc_transmit_apdu(card, &apdu);
if (r) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"%s: APDU transmit failed", sc_strerror(r));
sc_log(card->ctx, "%s: APDU transmit failed", sc_strerror(r));
goto err;
}
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
if (r) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"%s: Card returned error", sc_strerror(r));
sc_log(card->ctx, "%s: Card returned error", sc_strerror(r));
goto err;
}
}
@ -766,7 +801,8 @@ static int iso7816_set_security_env(sc_card_t *card,
sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num);
r = sc_transmit_apdu(card, &apdu);
sc_unlock(card);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
return sc_check_sw(card, apdu.sw1, apdu.sw2);
err:
if (locked)
@ -774,37 +810,44 @@ err:
return r;
}
static int iso7816_restore_security_env(sc_card_t *card, int se_num)
static int
iso7816_restore_security_env(struct sc_card *card, int se_num)
{
sc_apdu_t apdu;
struct sc_apdu apdu;
int r;
assert(card != NULL);
sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, se_num);
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
return sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
return r;
}
static int iso7816_compute_signature(sc_card_t *card,
const u8 * data, size_t datalen,
u8 * out, size_t outlen)
static int
iso7816_compute_signature(struct sc_card *card,
const u8 * data, size_t datalen,
u8 * out, size_t outlen)
{
int r;
sc_apdu_t apdu;
struct sc_apdu apdu;
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
assert(card != NULL && data != NULL && out != NULL);
if (datalen > 255)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
/* INS: 0x2A PERFORM SECURITY OPERATION
* P1: 0x9E Resp: Digital Signature
* P2: 0x9A Cmd: Input for Digital Signature */
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E,
0x9A);
sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A);
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf); /* FIXME */
apdu.le = 256;
@ -814,22 +857,28 @@ static int iso7816_compute_signature(sc_card_t *card,
apdu.lc = datalen;
apdu.datalen = datalen;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
memcpy(out, apdu.resp, len);
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, len);
LOG_FUNC_RETURN(card->ctx, len);
}
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
LOG_TEST_RET(card->ctx, r, "Card returned error");
LOG_FUNC_RETURN(card->ctx, r);
}
static int iso7816_decipher(sc_card_t *card,
const u8 * crgram, size_t crgram_len,
u8 * out, size_t outlen)
static int
iso7816_decipher(struct sc_card *card,
const u8 * crgram, size_t crgram_len,
u8 * out, size_t outlen)
{
int r;
sc_apdu_t apdu;
struct sc_apdu apdu;
u8 *sbuf = NULL;
assert(card != NULL && crgram != NULL && out != NULL);
@ -852,7 +901,7 @@ static int iso7816_decipher(sc_card_t *card,
/* Use APDU chaining with 2048bit RSA keys if the card does not do extended APDU-s */
if ((crgram_len+1 > 255) && !(card->caps & SC_CARD_CAP_APDU_EXT))
apdu.flags |= SC_APDU_FLAGS_CHAINING;
sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
memcpy(sbuf + 1, crgram, crgram_len);
apdu.data = sbuf;
@ -861,18 +910,21 @@ static int iso7816_decipher(sc_card_t *card,
r = sc_transmit_apdu(card, &apdu);
sc_mem_clear(sbuf, crgram_len + 1);
free(sbuf);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, apdu.resplen);
LOG_FUNC_RETURN(card->ctx, apdu.resplen);
else
SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
}
static int iso7816_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu,
static int
iso7816_build_pin_apdu(struct sc_card *card, struct sc_apdu *apdu,
struct sc_pin_cmd_data *data, u8 *buf, size_t buf_len)
{
int r, len = 0, pad = 0, use_pin_pad = 0, ins, p1 = 0;
switch (data->pin_type) {
case SC_AC_CHV:
break;
@ -900,7 +952,8 @@ static int iso7816_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu,
if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
return r;
len += r;
} else {
}
else {
/* implicit test */
p1 = 1;
}
@ -908,6 +961,14 @@ static int iso7816_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu,
data->pin2.offset = data->pin1.offset + len;
if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, pad)) < 0)
return r;
/* Special case - where provided the old PIN on the command line
* but expect the new one to be entered on the keypad.
*/
if (data->pin1.len && data->pin2.len == 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"Special case - initial pin provided - but new pin asked on keypad");
data->flags |= SC_PIN_CMD_IMPLICIT_CHANGE;
};
len += r;
break;
case SC_PIN_CMD_UNBLOCK:
@ -933,9 +994,7 @@ static int iso7816_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu,
return SC_ERROR_NOT_SUPPORTED;
}
sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT,
ins, p1, data->pin_reference);
sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, ins, p1, data->pin_reference);
apdu->lc = len;
apdu->datalen = len;
apdu->data = buf;
@ -944,10 +1003,11 @@ static int iso7816_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu,
return 0;
}
static int iso7816_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
int *tries_left)
static int
iso7816_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left)
{
sc_apdu_t local_apdu, *apdu;
struct sc_apdu local_apdu, *apdu;
int r;
u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
@ -973,23 +1033,21 @@ static int iso7816_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
/* Clear the buffer - it may contain pins */
sc_mem_clear(sbuf, sizeof(sbuf));
} else {
}
else {
/* Call the reader driver to collect
* the PIN and pass on the APDU to the card */
if (data->pin1.offset == 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"Card driver didn't set PIN offset");
sc_log(card->ctx, "Card driver didn't set PIN offset");
return SC_ERROR_INVALID_ARGUMENTS;
}
if (card->reader
&& card->reader->ops
&& card->reader->ops->perform_verify) {
if (card->reader && card->reader->ops && card->reader->ops->perform_verify) {
r = card->reader->ops->perform_verify(card->reader, data);
/* sw1/sw2 filled in by reader driver */
} else {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"Card reader driver does not support "
"PIN entry through reader key pad");
}
else {
sc_log(card->ctx, "Card reader driver does not support "
"PIN entry through reader key pad");
r = SC_ERROR_NOT_SUPPORTED;
}
}
@ -998,7 +1056,7 @@ static int iso7816_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
if (data->apdu == &local_apdu)
data->apdu = NULL;
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
if (apdu->sw1 == 0x63) {
if ((apdu->sw2 & 0xF0) == 0xC0 && tries_left != NULL)
*tries_left = apdu->sw2 & 0x0F;
@ -1007,7 +1065,9 @@ static int iso7816_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
return sc_check_sw(card, apdu->sw1, apdu->sw2);
}
static int no_match(sc_card_t *card)
static int
no_match(struct sc_card *card)
{
return 0;
}

View File

@ -12,15 +12,19 @@ extern "C" {
#define ISO7816_FILE_TYPE_TRANSPARENT_EF 0x01
#define ISO7816_FILE_TYPE_DF 0x38
#define ISO7816_TAG_FCI 0x6F
#define ISO7816_TAG_FCI 0x6F
#define ISO7816_TAG_FCP 0x62
#define ISO7816_TAG_FCP_SIZE 0x80
#define ISO7816_TAG_FCP_TYPE 0x82
#define ISO7816_TAG_FCP_ID 0x83
#define ISO7816_TAG_FCP_ACLS 0x86
#define ISO7816_TAG_FCP 0x62
#define ISO7816_TAG_FCP_SIZE 0x80
#define ISO7816_TAG_FCP_SIZE_FULL 0x81
#define ISO7816_TAG_FCP_TYPE 0x82
#define ISO7816_TAG_FCP_FID 0x83
#define ISO7816_TAG_FCP_DF_NAME 0x84
#define ISO7816_TAG_FCP_PROP_INFO 0x85
#define ISO7816_TAG_FCP_ACLS 0x86
#define ISO7816_TAG_FCP_LCS 0x8A
/* ISO7816 interindustry data tags */
/* ISO7816 interindustry data tags */
#define ISO7816_II_CATEGORY_TLV 0x80
#define ISO7816_II_CATEGORY_NOT_TLV 0x00

View File

@ -99,6 +99,8 @@ sc_file_set_sec_attr
sc_file_set_type_attr
sc_file_valid
sc_format_apdu
sc_allocate_apdu
sc_free_apdu
sc_bytes2apdu
sc_format_asn1_entry
sc_format_oid
@ -300,12 +302,16 @@ sc_pkcs15init_verify_secret
sc_pkcs15init_sanity_check
sc_pkcs15init_finalize_profile
sc_card_find_rsa_alg
sc_check_apdu
sc_print_cache
sc_find_app
sc_remote_data_init
sc_crc32
sc_pkcs15_convert_prkey
sc_pkcs15_convert_pubkey
sc_sm_parse_answer
sc_sm_update_apdu_response
sc_sm_single_transmit
iasecc_sdo_encode_update_field
iasecc_sm_create_file
iasecc_sm_delete_file

View File

@ -60,7 +60,7 @@ void sc_do_log_noframe(sc_context_t *ctx, int level, const char *format, va_list
static void sc_do_log_va(sc_context_t *ctx, int level, const char *file, int line, const char *func, const char *format, va_list args)
{
char buf[1836], *p;
char buf[4096], *p;
int r;
size_t left;
#ifdef _WIN32

View File

@ -166,7 +166,7 @@ typedef struct sc_security_env {
unsigned int algorithm_ref;
struct sc_path file_ref;
u8 key_ref[8];
unsigned char key_ref[8];
size_t key_ref_len;
struct sc_supported_algo_info supported_algos[SC_MAX_SUPPORTED_ALGORITHMS];
@ -719,10 +719,14 @@ typedef struct sc_context {
* @param apdu sc_apdu_t object of the APDU to be send
* @return SC_SUCCESS on succcess and an error code otherwise
*/
int sc_transmit_apdu(struct sc_card *card, sc_apdu_t *apdu);
int sc_transmit_apdu(struct sc_card *, struct sc_apdu *);
void sc_format_apdu(struct sc_card *card, sc_apdu_t *apdu, int cse, int ins,
int p1, int p2);
void sc_format_apdu(struct sc_card *, struct sc_apdu *, int, int, int, int);
int sc_check_apdu(struct sc_card *, const struct sc_apdu *);
struct sc_apdu *sc_allocate_apdu(struct sc_apdu *, unsigned);
void sc_free_apdu(struct sc_apdu *);
/** Transforms an APDU from binary to its @c sc_apdu_t representation
* @param ctx sc_context_t object (used for logging)

View File

@ -34,13 +34,13 @@
#include "pkcs15.h"
static int
parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, struct sc_pkcs15_cert *cert)
parse_x509_cert(sc_context_t *ctx, struct sc_pkcs15_der *der, struct sc_pkcs15_cert *cert)
{
int r;
struct sc_algorithm_id sig_alg;
struct sc_pkcs15_pubkey * pubkey = NULL;
u8 *serial = NULL;
size_t serial_len = 0;
struct sc_pkcs15_pubkey *pubkey = NULL;
unsigned char *serial = NULL, *issuer = NULL, *subject = NULL, *buf = der->value;
size_t serial_len = 0, issuer_len = 0, subject_len = 0, data_len = 0, buflen = der->len;
struct sc_asn1_entry asn1_version[] = {
{ "version", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, &cert->version, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
@ -61,9 +61,9 @@ parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, struct sc_pkcs1
{ "version", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_version, NULL },
{ "serialNumber", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC, &serial, &serial_len },
{ "signature", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
{ "issuer", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &cert->issuer, &cert->issuer_len },
{ "issuer", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &issuer, &issuer_len },
{ "validity", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
{ "subject", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &cert->subject, &cert->subject_len },
{ "subject", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &subject, &subject_len },
/* Use a callback to get the algorithm, parameters and pubkey into sc_pkcs15_pubkey */
{ "subjectPublicKeyInfo",SC_ASN1_CALLBACK, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, sc_pkcs15_pubkey_from_spki, &pubkey },
{ "extensions", SC_ASN1_STRUCT, SC_ASN1_CTX | 3 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_extensions, NULL },
@ -79,6 +79,15 @@ parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, struct sc_pkcs1
{ "serialNumber", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
struct sc_asn1_entry asn1_subject[] = {
{ "subject", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
struct sc_asn1_entry asn1_issuer[] = {
{ "issuer", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
const u8 *obj;
size_t objlen;
@ -87,30 +96,46 @@ parse_x509_cert(sc_context_t *ctx, const u8 *buf, size_t buflen, struct sc_pkcs1
if (obj == NULL)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "X.509 certificate not found");
cert->data.len = objlen + (obj - buf);
data_len = objlen + (obj - buf);
cert->data.value = malloc(data_len);
if (!cert->data.value)
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
memcpy(cert->data.value, buf, data_len);
cert->data.len = data_len;
r = sc_asn1_decode(ctx, asn1_cert, obj, objlen, NULL, NULL);
LOG_TEST_RET(ctx, r, "ASN.1 parsing of certificate failed");
cert->version++;
if (pubkey) {
cert->key = pubkey;
pubkey = NULL;
}
else {
if (!pubkey)
LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "Unable to decode subjectPublicKeyInfo from cert");
}
cert->key = pubkey;
sc_asn1_clear_algorithm_id(&sig_alg);
if (r < 0)
return r;
if (serial && serial_len) {
sc_format_asn1_entry(asn1_serial_number + 0, serial, &serial_len, 1);
r = sc_asn1_encode(ctx, asn1_serial_number, &cert->serial, &cert->serial_len);
free(serial);
LOG_TEST_RET(ctx, r, "ASN.1 encoding of serial failed");
}
return r;
if (subject && subject_len) {
sc_format_asn1_entry(asn1_subject + 0, subject, &subject_len, 1);
r = sc_asn1_encode(ctx, asn1_subject, &cert->subject, &cert->subject_len);
free(subject);
LOG_TEST_RET(ctx, r, "ASN.1 encoding of subject");
}
if (issuer && issuer_len) {
sc_format_asn1_entry(asn1_issuer + 0, issuer, &issuer_len, 1);
r = sc_asn1_encode(ctx, asn1_issuer, &cert->issuer, &cert->issuer_len);
free(issuer);
LOG_TEST_RET(ctx, r, "ASN.1 encoding of issuer");
}
return SC_SUCCESS;
}
@ -125,7 +150,7 @@ sc_pkcs15_pubkey_from_cert(struct sc_context *ctx,
if (cert == NULL)
return SC_ERROR_OUT_OF_MEMORY;
rv = parse_x509_cert(ctx, cert_blob->value, cert_blob->len, cert);
rv = parse_x509_cert(ctx, cert_blob, cert);
*out = cert->key;
cert->key = NULL;
@ -139,43 +164,44 @@ int
sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_cert_info *info,
struct sc_pkcs15_cert **cert_out)
{
struct sc_pkcs15_cert *cert;
struct sc_context *ctx = NULL;
struct sc_pkcs15_cert *cert = NULL;
struct sc_pkcs15_der der;
int r;
assert(p15card != NULL && info != NULL && cert_out != NULL);
LOG_FUNC_CALLED(p15card->card->ctx);
ctx = p15card->card->ctx;
LOG_FUNC_CALLED(ctx);
if (info->value.len && info->value.value) {
sc_der_copy(&der, &info->value);
}
else if (info->path.len) {
r = sc_pkcs15_read_file(p15card, &info->path, &der.value, &der.len);
if (r)
return r;
LOG_TEST_RET(ctx, r, "Unable to read certificate file.");
}
else {
return SC_ERROR_OBJECT_NOT_FOUND;
LOG_FUNC_RETURN(ctx, SC_ERROR_OBJECT_NOT_FOUND);
}
cert = malloc(sizeof(struct sc_pkcs15_cert));
if (cert == NULL) {
free(der.value);
return SC_ERROR_OUT_OF_MEMORY;
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
}
memset(cert, 0, sizeof(struct sc_pkcs15_cert));
if (parse_x509_cert(p15card->card->ctx, der.value, der.len, cert)) {
if (parse_x509_cert(ctx, &der, cert)) {
free(der.value);
sc_pkcs15_free_certificate(cert);
return SC_ERROR_INVALID_ASN1_OBJECT;
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ASN1_OBJECT);
}
free(der.value);
cert->data = der;
*cert_out = cert;
return SC_SUCCESS;
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
static const struct sc_asn1_entry c_asn1_cred_ident[] = {
{ "idType", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
{ "idValue", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL },

View File

@ -39,35 +39,39 @@ static const struct sc_asn1_entry c_asn1_data_object[] = {
{ NULL, 0, 0, 0, NULL, NULL }
};
int sc_pkcs15_read_data_object(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_data_info *info,
struct sc_pkcs15_data **data_object_out)
int
sc_pkcs15_read_data_object(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_data_info *info,
struct sc_pkcs15_data **data_object_out)
{
int r;
struct sc_context *ctx = p15card->card->ctx;
struct sc_pkcs15_data *data_object;
u8 *data = NULL;
size_t len;
struct sc_pkcs15_der der;
int r;
if (p15card == NULL || info == NULL || data_object_out == NULL)
return SC_ERROR_INVALID_ARGUMENTS;
SC_FUNC_CALLED(p15card->card->ctx, SC_LOG_DEBUG_VERBOSE);
LOG_FUNC_CALLED(ctx);
if (!info || !data_object_out)
LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
r = sc_pkcs15_read_file(p15card, &info->path, &data, &len);
if (r)
return r;
data_object = malloc(sizeof(struct sc_pkcs15_data));
if (data_object == NULL) {
free(data);
return SC_ERROR_OUT_OF_MEMORY;
if (!info->data.value) {
r = sc_pkcs15_read_file(p15card, &info->path, &info->data.value, &info->data.len);
LOG_TEST_RET(ctx, r, "Cannot get DATA object data");
}
memset(data_object, 0, sizeof(struct sc_pkcs15_data));
data_object->data = data;
data_object->data_len = len;
sc_der_copy(&der, &info->data);
data_object = calloc(sizeof(struct sc_pkcs15_data), 1);
if (!data_object && !der.value)
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate memory for data object");
data_object->data = der.value;
data_object->data_len = der.len;
*data_object_out = data_object;
return SC_SUCCESS;
LOG_FUNC_RETURN(ctx,SC_SUCCESS);
}
static const struct sc_asn1_entry c_asn1_data[] = {
{ "data", SC_ASN1_PKCS15_OBJECT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
@ -173,7 +177,10 @@ void sc_pkcs15_free_data_object(struct sc_pkcs15_data *data_object)
free(data_object);
}
void sc_pkcs15_free_data_info(sc_pkcs15_data_info_t *data)
void sc_pkcs15_free_data_info(struct sc_pkcs15_data_info *info)
{
free(data);
if (info && info->data.value && info->data.len)
free(info->data.value);
free(info);
}

View File

@ -1,7 +1,7 @@
/*
* PKCS15 emulation layer for EstEID card.
*
* Copyright (C) 2004, Martin Paljak <martin@paljak.pri.ee>
* Copyright (C) 2004, Martin Paljak <martin@martinpaljak.net>
* Copyright (C) 2004, Bud P. Bruegger <bud@comune.grosseto.it>
* Copyright (C) 2004, Antonino Iacono <ant_iacono@tin.it>
* Copyright (C) 2003, Olaf Kirch <okir@suse.de>

View File

@ -14,7 +14,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Initially written by David Mattes (david.mattes@boeing.com) */
/* Initially written by David Mattes <david.mattes@boeing.com> */
/* Support for multiple key containers by Lukas Wunner <lukas@wunner.de> */
#include "config.h"
@ -28,6 +29,14 @@
#define MANU_ID "Gemplus"
#define APPLET_NAME "GemSAFE V1"
#define DRIVER_SERIAL_NUMBER "v0.9"
#define GEMSAFE_APP_PATH "3F001600"
#define GEMSAFE_PATH "3F0016000004"
/* Apparently, the Applet max read "quanta" is 248 bytes
* Gemalto ClassicClient reads files in chunks of 238 bytes
*/
#define GEMSAFE_READ_QUANTUM 248
#define GEMSAFE_MAX_OBJLEN 28672
int sc_pkcs15emu_gemsafeV1_init_ex(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
@ -55,43 +64,67 @@ sc_pkcs15emu_add_prkey(sc_pkcs15_card_t *p15card,
const sc_pkcs15_id_t *auth_id, int obj_flags);
typedef struct cdata_st {
const char *label;
char *label;
int authority;
const char *path;
size_t index;
size_t count;
const char *id;
int obj_flags;
} cdata;
const cdata gemsafe_cert[] = {
{"DS certificate", 0, "3F0016000004","45", SC_PKCS15_CO_FLAG_MODIFIABLE},
{NULL, 0, NULL, 0, 0}
const unsigned int gemsafe_cert_max = 12;
cdata gemsafe_cert[] = {
{"DS certificate #1", 0, GEMSAFE_PATH, 0, 0, "45", SC_PKCS15_CO_FLAG_MODIFIABLE},
{"DS certificate #2", 0, GEMSAFE_PATH, 0, 0, "46", SC_PKCS15_CO_FLAG_MODIFIABLE},
{"DS certificate #3", 0, GEMSAFE_PATH, 0, 0, "47", SC_PKCS15_CO_FLAG_MODIFIABLE},
{"DS certificate #4", 0, GEMSAFE_PATH, 0, 0, "48", SC_PKCS15_CO_FLAG_MODIFIABLE},
{"DS certificate #5", 0, GEMSAFE_PATH, 0, 0, "49", SC_PKCS15_CO_FLAG_MODIFIABLE},
{"DS certificate #6", 0, GEMSAFE_PATH, 0, 0, "50", SC_PKCS15_CO_FLAG_MODIFIABLE},
{"DS certificate #7", 0, GEMSAFE_PATH, 0, 0, "51", SC_PKCS15_CO_FLAG_MODIFIABLE},
{"DS certificate #8", 0, GEMSAFE_PATH, 0, 0, "52", SC_PKCS15_CO_FLAG_MODIFIABLE},
{"DS certificate #9", 0, GEMSAFE_PATH, 0, 0, "53", SC_PKCS15_CO_FLAG_MODIFIABLE},
{"DS certificate #10", 0, GEMSAFE_PATH, 0, 0, "54", SC_PKCS15_CO_FLAG_MODIFIABLE},
{"DS certificate #11", 0, GEMSAFE_PATH, 0, 0, "55", SC_PKCS15_CO_FLAG_MODIFIABLE},
{"DS certificate #12", 0, GEMSAFE_PATH, 0, 0, "56", SC_PKCS15_CO_FLAG_MODIFIABLE},
};
typedef struct pdata_st {
const u8 atr[SC_MAX_ATR_SIZE];
const size_t atr_len;
const char *id;
const char *label;
const char *path;
int ref;
int type;
unsigned int maxlen;
unsigned int minlen;
int flags;
int tries_left;
const int ref;
const int type;
const unsigned int maxlen;
const unsigned int minlen;
const int flags;
const int tries_left;
const char pad_char;
int obj_flags;
const int obj_flags;
} pindata;
const unsigned int gemsafe_pin_max = 2;
const pindata gemsafe_pin[] = {
{ "01", "DS pin", NULL, 0x01, SC_PKCS15_PIN_TYPE_BCD,
/* ATR-specific PIN policies, first match found is used: */
{ {0x3B, 0x7D, 0x96, 0x00, 0x00, 0x80, 0x31, 0x80, 0x65,
0xB0, 0x83, 0x11, 0x48, 0xC8, 0x83, 0x00, 0x90, 0x00}, 18,
"01", "DS pin", GEMSAFE_PATH, 0x01, SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
8, 4, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL,
3, 0x00, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE },
/* default PIN policy comes last: */
{ { 0 }, 0,
"01", "DS pin", GEMSAFE_PATH, 0x01, SC_PKCS15_PIN_TYPE_BCD,
16, 6, SC_PKCS15_PIN_FLAG_NEEDS_PADDING | SC_PKCS15_PIN_FLAG_LOCAL,
3, 0xFF,
SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE },
{ NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0 }
3, 0xFF, SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE }
};
typedef struct prdata_st {
const char *id;
const char *label;
char *label;
unsigned int modulus_len;
int usage;
const char *path;
@ -111,100 +144,146 @@ typedef struct prdata_st {
SC_PKCS15_PRKEY_USAGE_UNWRAP | \
SC_PKCS15_PRKEY_USAGE_SIGN
const prdata gemsafe_prkeys[] = {
{ "45", "DS key", 1024, USAGE_AUT, NULL,
0x03, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ NULL, NULL, 0, 0, NULL, 0, NULL, 0}
prdata gemsafe_prkeys[] = {
{ "45", "DS key #1", 1024, USAGE_AUT, GEMSAFE_PATH, 0x03, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ "46", "DS key #2", 1024, USAGE_AUT, GEMSAFE_PATH, 0x04, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ "47", "DS key #3", 1024, USAGE_AUT, GEMSAFE_PATH, 0x05, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ "48", "DS key #4", 1024, USAGE_AUT, GEMSAFE_PATH, 0x06, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ "49", "DS key #5", 1024, USAGE_AUT, GEMSAFE_PATH, 0x07, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ "50", "DS key #6", 1024, USAGE_AUT, GEMSAFE_PATH, 0x08, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ "51", "DS key #7", 1024, USAGE_AUT, GEMSAFE_PATH, 0x09, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ "52", "DS key #8", 1024, USAGE_AUT, GEMSAFE_PATH, 0x0a, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ "53", "DS key #9", 1024, USAGE_AUT, GEMSAFE_PATH, 0x0b, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ "54", "DS key #10", 1024, USAGE_AUT, GEMSAFE_PATH, 0x0c, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ "55", "DS key #11", 1024, USAGE_AUT, GEMSAFE_PATH, 0x0d, "01", SC_PKCS15_CO_FLAG_PRIVATE},
{ "56", "DS key #12", 1024, USAGE_AUT, GEMSAFE_PATH, 0x0e, "01", SC_PKCS15_CO_FLAG_PRIVATE},
};
static int gemsafe_get_cert_len(sc_card_t *card, sc_path_t *path,
int *key_ref)
static int gemsafe_get_cert_len(sc_card_t *card)
{
const char *fn_name = "gemsafe_get_cert_len";
int r;
int ind;
u8 ibuf[248];
u8 ibuf[GEMSAFE_MAX_OBJLEN];
u8 *iptr;
struct sc_path path;
struct sc_file *file;
size_t objlen, certlen;
unsigned int block=0;
int found = 0;
unsigned int offset=0, index_local, i=0;
unsigned int ind, i=0;
r = sc_select_file(card, path, &file);
if (r < 0)
return 0;
sc_format_path(GEMSAFE_PATH, &path);
r = sc_select_file(card, &path, &file);
if (r != SC_SUCCESS || !file)
return SC_ERROR_INTERNAL;
/* Apparently, the Applet max read "quanta" is 248 bytes */
/* Initial read */
r = sc_read_binary(card, offset, ibuf, 248, 0);
r = sc_read_binary(card, 0, ibuf, GEMSAFE_READ_QUANTUM, 0);
if (r < 0)
return 0;
return SC_ERROR_INTERNAL;
/* Actual stored object size is encoded in first 2 bytes
* (allocated EF space is much greater!)
*/
objlen = (((size_t) ibuf[0]) << 8) | ibuf[1];
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s: Certificate object is of size: %d\n", fn_name, objlen);
if (objlen < 1 || objlen > 10240) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s: Invalid object size: %d\n", fn_name, objlen);
return 0;
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"Stored object is of size: %d\n", objlen);
if (objlen < 1 || objlen > GEMSAFE_MAX_OBJLEN) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"Invalid object size: %d\n", objlen);
return SC_ERROR_INTERNAL;
}
/*
* We need to find the private key associated with the cert
* It looks like the first thing in the block is a table of
* which keys are allocated.
* We will look for the first allocated key, and save the
* key_ref. The table is small and is in the first 248 bytes.
* If for some reason this is not true, we can still override
* the key_ref in the opensc.conf with flag = n.
/* It looks like the first thing in the block is a table of
* which keys are allocated. The table is small and is in the
* first 248 bytes. Example for a card with 10 key containers:
* 01 f0 00 03 03 b0 00 03 <= 1st key unallocated
* 01 f0 00 04 03 b0 00 04 <= 2nd key unallocated
* 01 fe 14 00 05 03 b0 00 05 <= 3rd key allocated
* 01 fe 14 01 06 03 b0 00 06 <= 4th key allocated
* 01 f0 00 07 03 b0 00 07 <= 5th key unallocated
* ...
* 01 f0 00 0c 03 b0 00 0c <= 10th key unallocated
* For allocated keys, the fourth byte seems to indicate the
* default key and the fifth byte indicates the key_ref of
* the private key.
*/
ind = 2; /* skip length */
while (ibuf[ind] == 0x01) {
if (ibuf[ind+1] == 0xFE) {
*key_ref = ibuf[ind+4];
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Using key_ref %d found at offset %d\n",
*key_ref, ind);
break;
gemsafe_prkeys[i].ref = ibuf[ind+4];
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"Key container %d is allocated and uses key_ref %d\n", i+1,
gemsafe_prkeys[i].ref);
ind += 9;
} else {
gemsafe_prkeys[i].label = NULL;
gemsafe_cert[i].label = NULL;
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"Key container %d is unallocated\n", i+1);
ind += 8;
}
ind = ind + 8;
i++;
}
/* Using (block+1) in while loop avoids using final cert object data block */
while (!found && ( (block+1) * 248 < objlen) ) {
/* Check current buffer */
for (i = 0; i < 247; i++) {
if (ibuf[i] == 0x30 && ibuf[i+1] == 0x82) {
found = 1;
break;
}
}
/* Delete additional key containers from the data structures if
* this card can't accomodate them.
*/
for (; i < gemsafe_cert_max; i++) {
gemsafe_prkeys[i].label = NULL;
gemsafe_cert[i].label = NULL;
}
/* Grab another buffer */
if (!found) {
block++;
offset = block*248;
r = sc_read_binary(card, offset, ibuf, 248, 0);
/* Read entire file, then dissect in memory.
* Gemalto ClassicClient seems to do it the same way.
*/
iptr = ibuf + GEMSAFE_READ_QUANTUM;
while ((size_t)(iptr - ibuf) < objlen) {
r = sc_read_binary(card, iptr - ibuf, iptr,
MIN(GEMSAFE_READ_QUANTUM, objlen - (iptr - ibuf)), 0);
if (r < 0) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s: Could not read cert object\n", fn_name);
return 0;
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"Could not read cert object\n");
return SC_ERROR_INTERNAL;
}
}
iptr += GEMSAFE_READ_QUANTUM;
}
index_local = block*248 + i;
/* Search buffer for certificates, they start with 0x3082. */
i = 0;
while (ind < objlen - 1) {
if (ibuf[ind] == 0x30 && ibuf[ind+1] == 0x82) {
/* Find next allocated key container */
while (i < gemsafe_cert_max && gemsafe_cert[i].label == NULL)
i++;
if (i == gemsafe_cert_max) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"Warning: Found orphaned certificate at offset %d\n", ind);
return SC_SUCCESS;
}
/* DER cert len is encoded this way */
certlen = ((((size_t) ibuf[ind+2]) << 8) | ibuf[ind+3]) + 4;
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"Found certificate of key container %d at offset %d, len %d\n",
i+1, ind, certlen);
gemsafe_cert[i].index = ind;
gemsafe_cert[i].count = certlen;
ind += certlen;
i++;
} else
ind++;
}
/* DER Cert len is encoded this way */
certlen = ((((size_t) ibuf[i+2]) << 8) | ibuf[i+3]) + 4;
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "%s: certlen: %04X\n", fn_name, certlen);
path->index = index_local;
path->count = certlen;
return 1;
/* Delete additional key containers from the data structures if
* they're missing on the card.
*/
for (; i < gemsafe_cert_max; i++) {
if (gemsafe_cert[i].label) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
"Warning: Certificate of key container %d is missing\n", i+1);
gemsafe_prkeys[i].label = NULL;
gemsafe_cert[i].label = NULL;
}
}
return SC_SUCCESS;
}
static int gemsafe_detect_card( sc_pkcs15_card_t *p15card)
@ -212,142 +291,162 @@ static int gemsafe_detect_card( sc_pkcs15_card_t *p15card)
if (strcmp(p15card->card->name, "GemSAFE V1"))
return SC_ERROR_WRONG_CARD;
return SC_SUCCESS;
return SC_SUCCESS;
}
static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card)
{
const char *fn_name = "sc_pkcs15emu_gemsafe_init";
int r;
unsigned int i;
struct sc_path path;
struct sc_file *file = NULL;
struct sc_card *card = p15card->card;
struct sc_apdu apdu;
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
int r, i;
int key_ref = 0x03;
struct sc_path path;
struct sc_file *file = NULL;
struct sc_card *card = p15card->card;
struct sc_apdu apdu;
u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting pkcs15 parameters\n");
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "%s: Setting pkcs15 parameters\n", fn_name);
if (p15card->tokeninfo->label)
free(p15card->tokeninfo->label);
p15card->tokeninfo->label = malloc(strlen(APPLET_NAME) + 1);
if (!p15card->tokeninfo->label)
return SC_ERROR_INTERNAL;
strcpy(p15card->tokeninfo->label, APPLET_NAME);
if (p15card->tokeninfo->label)
free(p15card->tokeninfo->label);
p15card->tokeninfo->label = malloc(strlen(APPLET_NAME) + 1);
if (!p15card->tokeninfo->label)
return SC_ERROR_INTERNAL;
strcpy(p15card->tokeninfo->label, APPLET_NAME);
if (p15card->tokeninfo->serial_number)
free(p15card->tokeninfo->serial_number);
p15card->tokeninfo->serial_number = malloc(strlen(DRIVER_SERIAL_NUMBER) + 1);
if (!p15card->tokeninfo->serial_number)
return SC_ERROR_INTERNAL;
strcpy(p15card->tokeninfo->serial_number, DRIVER_SERIAL_NUMBER);
if (p15card->tokeninfo->serial_number)
free(p15card->tokeninfo->serial_number);
p15card->tokeninfo->serial_number = malloc(strlen(DRIVER_SERIAL_NUMBER) + 1);
if (!p15card->tokeninfo->serial_number)
return SC_ERROR_INTERNAL;
strcpy(p15card->tokeninfo->serial_number, DRIVER_SERIAL_NUMBER);
/* the GemSAFE applet version number */
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0xdf, 0x03);
apdu.cla = 0x80;
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
/* Manual says Le=0x05, but should be 0x08 to return full version numer */
apdu.le = 0x08;
apdu.lc = 0;
apdu.datalen = 0;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
return SC_ERROR_INTERNAL;
if (r != SC_SUCCESS)
return SC_ERROR_INTERNAL;
/* the GemSAFE applet version number */
sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0xdf, 0x03);
apdu.cla = 0x80;
apdu.resp = rbuf;
apdu.resplen = sizeof(rbuf);
/* Manual says Le=0x05, but should be 0x08 to return full version numer */
apdu.le = 0x08;
apdu.lc = 0;
apdu.datalen = 0;
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r, "APDU transmit failed");
if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
return SC_ERROR_INTERNAL;
if (r != SC_SUCCESS)
return SC_ERROR_INTERNAL;
/* the manufacturer ID, in this case GemPlus */
if (p15card->tokeninfo->manufacturer_id)
free(p15card->tokeninfo->manufacturer_id);
p15card->tokeninfo->manufacturer_id = malloc(strlen(MANU_ID) + 1);
if (!p15card->tokeninfo->manufacturer_id)
return SC_ERROR_INTERNAL;
strcpy(p15card->tokeninfo->manufacturer_id, MANU_ID);
/* the manufacturer ID, in this case GemPlus */
if (p15card->tokeninfo->manufacturer_id)
free(p15card->tokeninfo->manufacturer_id);
p15card->tokeninfo->manufacturer_id = malloc(strlen(MANU_ID) + 1);
if (!p15card->tokeninfo->manufacturer_id)
return SC_ERROR_INTERNAL;
strcpy(p15card->tokeninfo->manufacturer_id, MANU_ID);
/* determine allocated key containers and length of certificates */
r = gemsafe_get_cert_len(card);
if (r != SC_SUCCESS)
return SC_ERROR_INTERNAL;
/* set certs */
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "%s: Setting certificate\n", fn_name);
for (i = 0; gemsafe_cert[i].label; i++) {
struct sc_pkcs15_id p15Id;
/* set certs */
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting certificates\n");
for (i = 0; i < gemsafe_cert_max; i++) {
struct sc_pkcs15_id p15Id;
struct sc_path path;
sc_format_path(gemsafe_cert[i].path, &path);
if (!gemsafe_get_cert_len(card, &path, &key_ref))
/* skip errors */
continue;
sc_pkcs15_format_id(gemsafe_cert[i].id, &p15Id);
sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509,
gemsafe_cert[i].authority, &path, &p15Id,
gemsafe_cert[i].label, gemsafe_cert[i].obj_flags);
}
/* set gemsafe_pin */
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "%s: Setting PIN\n", fn_name);
for (i = 0; gemsafe_pin[i].label; i++) {
struct sc_pkcs15_id p15Id;
if (gemsafe_cert[i].label == NULL)
continue;
sc_format_path(gemsafe_cert[i].path, &path);
sc_pkcs15_format_id(gemsafe_cert[i].id, &p15Id);
path.index = gemsafe_cert[i].index;
path.count = gemsafe_cert[i].count;
sc_pkcs15emu_add_cert(p15card, SC_PKCS15_TYPE_CERT_X509,
gemsafe_cert[i].authority, &path, &p15Id,
gemsafe_cert[i].label, gemsafe_cert[i].obj_flags);
}
sc_pkcs15_format_id(gemsafe_pin[i].id, &p15Id);
sc_pkcs15emu_add_pin(p15card, &p15Id, gemsafe_pin[i].label,
&path, gemsafe_pin[i].ref, gemsafe_pin[i].type,
gemsafe_pin[i].minlen, gemsafe_pin[i].maxlen,
gemsafe_pin[i].flags,
gemsafe_pin[i].tries_left, gemsafe_pin[i].pad_char,
gemsafe_pin[i].obj_flags);
}
/* set private keys */
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "%s: Setting private key\n", fn_name);
for (i = 0; gemsafe_prkeys[i].label; i++) {
struct sc_pkcs15_id p15Id,
authId, *pauthId;
sc_pkcs15_format_id(gemsafe_prkeys[i].id, &p15Id);
if (gemsafe_prkeys[i].auth_id) {
sc_pkcs15_format_id(gemsafe_prkeys[i].auth_id, &authId);
pauthId = &authId;
} else
pauthId = NULL;
/*
* the key ref may be different for different sites
* by adding flags=n where the low order 4 bits can be
* the key ref we can force it.
*/
if ( p15card->card->flags & 0x0F) {
key_ref = p15card->card->flags & 0x0F;
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
"Overriding key_ref with %d\n", key_ref);
}
sc_pkcs15emu_add_prkey(p15card, &p15Id, gemsafe_prkeys[i].label,
SC_PKCS15_TYPE_PRKEY_RSA,
gemsafe_prkeys[i].modulus_len, gemsafe_prkeys[i].usage,
&path, key_ref, pauthId,
gemsafe_prkeys[i].obj_flags);
}
/* set gemsafe_pin */
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting PIN\n");
for (i=0; i < gemsafe_pin_max; i++) {
struct sc_pkcs15_id p15Id;
struct sc_path path;
/* select the application DF */
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,"%s: Selecting application DF\n", fn_name);
sc_format_path("3F001600", &path);
r = sc_select_file(card, &path, &file);
if (r != SC_SUCCESS || !file)
return SC_ERROR_INTERNAL;
/* set the application DF */
if (p15card->file_app)
free(p15card->file_app);
p15card->file_app = file;
sc_pkcs15_format_id(gemsafe_pin[i].id, &p15Id);
sc_format_path(gemsafe_pin[i].path, &path);
if (gemsafe_pin[i].atr_len == 0 ||
(gemsafe_pin[i].atr_len == p15card->card->atr.len &&
memcmp(p15card->card->atr.value, gemsafe_pin[i].atr,
p15card->card->atr.len) == 0)) {
sc_pkcs15emu_add_pin(p15card, &p15Id, gemsafe_pin[i].label,
&path, gemsafe_pin[i].ref, gemsafe_pin[i].type,
gemsafe_pin[i].minlen, gemsafe_pin[i].maxlen,
gemsafe_pin[i].flags, gemsafe_pin[i].tries_left,
gemsafe_pin[i].pad_char, gemsafe_pin[i].obj_flags);
break;
}
};
return SC_SUCCESS;
/* set private keys */
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "Setting private keys\n");
for (i = 0; i < gemsafe_cert_max; i++) {
struct sc_pkcs15_id p15Id, authId, *pauthId;
struct sc_path path;
int key_ref = 0x03;
if (gemsafe_prkeys[i].label == NULL)
continue;
sc_pkcs15_format_id(gemsafe_prkeys[i].id, &p15Id);
if (gemsafe_prkeys[i].auth_id) {
sc_pkcs15_format_id(gemsafe_prkeys[i].auth_id, &authId);
pauthId = &authId;
} else
pauthId = NULL;
sc_format_path(gemsafe_prkeys[i].path, &path);
/*
* The key ref may be different for different sites;
* by adding flags=n where the low order 4 bits can be
* the key ref we can force it.
*/
if ( p15card->card->flags & 0x0F) {
key_ref = p15card->card->flags & 0x0F;
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,
"Overriding key_ref %d with %d\n",
gemsafe_prkeys[i].ref, key_ref);
} else
key_ref = gemsafe_prkeys[i].ref;
sc_pkcs15emu_add_prkey(p15card, &p15Id, gemsafe_prkeys[i].label,
SC_PKCS15_TYPE_PRKEY_RSA,
gemsafe_prkeys[i].modulus_len, gemsafe_prkeys[i].usage,
&path, key_ref, pauthId,
gemsafe_prkeys[i].obj_flags);
}
/* select the application DF */
sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL,"Selecting application DF\n");
sc_format_path(GEMSAFE_APP_PATH, &path);
r = sc_select_file(card, &path, &file);
if (r != SC_SUCCESS || !file)
return SC_ERROR_INTERNAL;
/* set the application DF */
if (p15card->file_app)
free(p15card->file_app);
p15card->file_app = file;
return SC_SUCCESS;
}
int sc_pkcs15emu_gemsafeV1_init_ex( sc_pkcs15_card_t *p15card,
sc_pkcs15emu_opt_t *opts)
{
if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
return sc_pkcs15emu_gemsafeV1_init(p15card);
else {
int r = gemsafe_detect_card(p15card);
if (r)
return SC_ERROR_WRONG_CARD;
return sc_pkcs15emu_gemsafeV1_init(p15card);
}
if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
return sc_pkcs15emu_gemsafeV1_init(p15card);
else {
int r = gemsafe_detect_card(p15card);
if (r)
return SC_ERROR_WRONG_CARD;
return sc_pkcs15emu_gemsafeV1_init(p15card);
}
}
static sc_pkcs15_df_t *
@ -462,7 +561,6 @@ sc_pkcs15emu_add_cert(sc_pkcs15_card_t *p15card,
const sc_pkcs15_id_t *id,
const char *label, int obj_flags)
{
/* const char *label = "Certificate"; */
sc_pkcs15_cert_info_t *info;
info = calloc(1, sizeof(*info));
info->id = *id;

View File

@ -199,14 +199,14 @@ sc_oberthur_get_certificate_authority(struct sc_pkcs15_der *der, int *out_author
buf_mem.data = malloc(der->len);
if (!buf_mem.data)
return SC_ERROR_MEMORY_FAILURE;
return SC_ERROR_OUT_OF_MEMORY;
memcpy(buf_mem.data, der->value, der->len);
buf_mem.max = buf_mem.length = der->len;
bio = BIO_new(BIO_s_mem());
if(!bio)
return SC_ERROR_MEMORY_FAILURE;
return SC_ERROR_OUT_OF_MEMORY;
BIO_set_mem_buf(bio, &buf_mem, BIO_NOCLOSE);
x = d2i_X509_bio(bio, 0);
@ -259,7 +259,7 @@ sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path,
*out = calloc(sz, 1);
if (*out == NULL)
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_MEMORY_FAILURE, "Cannot read oberthur file");
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY, "Cannot read oberthur file");
if (file->ef_structure == SC_FILE_EF_TRANSPARENT) {
rv = sc_read_binary(card, 0, *out, sz, 0);
@ -395,7 +395,7 @@ sc_oberthur_parse_containers (struct sc_pkcs15_card *p15card,
cont = (struct container *)calloc(sizeof(struct container), 1);
if (!cont)
return SC_ERROR_MEMORY_FAILURE;
return SC_ERROR_OUT_OF_MEMORY;
cont->exchange.id_pub = *ptr * 0x100 + *(ptr + 1); ptr += 2;
cont->exchange.id_prv = *ptr * 0x100 + *(ptr + 1); ptr += 2;
@ -787,7 +787,7 @@ sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *p15card,
if (len) {
kinfo.subject.value = malloc(len);
if (!kinfo.subject.value)
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_MEMORY_FAILURE, "Failed to add private key: memory allocation error");
SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY, "Failed to add private key: memory allocation error");
kinfo.subject.len = len;
memcpy(kinfo.subject.value, info_blob + offs + 2, len);
}

View File

@ -2,7 +2,7 @@
* PKCS15 emulation layer for Portugal eID card.
*
* Copyright (C) 2009, Joao Poupino <joao.poupino@ist.utl.pt>
* Copyright (C) 2004, Martin Paljak <martin@paljak.pri.ee>
* Copyright (C) 2004, Martin Paljak <martin@martinpaljak.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -226,7 +226,6 @@ static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card)
/* Add objects */
for (i = 0; i < 3; i++) {
static const char *object_ids[3] = {"1", "2", "3"};
static const char *object_oids[3] = {"-1", "-1", "-1"};
static const char *object_labels[3] = {"Citizen Data",
"Citizen Address Data",
"Citizen Notepad"};
@ -245,9 +244,6 @@ static int sc_pkcs15emu_pteid_init(sc_pkcs15_card_t * p15card)
sc_pkcs15_format_id(object_ids[i], &obj_info.id);
sc_format_path(object_paths[i], &obj_info.path);
r = sc_format_oid(&obj_info.app_oid, object_oids[i]);
if (r != SC_SUCCESS)
goto end;
strlcpy(obj_info.app_label, object_labels[i], SC_PKCS15_MAX_LABEL_SIZE);
if (object_authids[i] != NULL)
sc_pkcs15_format_id(object_authids[i], &obj_obj.auth_id);

View File

@ -268,7 +268,7 @@ static int sc_pkcs15emu_sc_hsm_add_pubkey(sc_pkcs15_card_t *p15card, sc_pkcs15_p
sc_pkcs15_pubkey_info_t pubkey_info;
sc_pkcs15_object_t pubkey_obj;
struct sc_pkcs15_pubkey pubkey;
u8 efbin[512];
u8 efbin[1024];
sc_cvc_t cvc;
u8 *cvcpo;
size_t cvclen;
@ -661,7 +661,9 @@ static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card)
r = sc_pkcs15emu_sc_hsm_add_cd(p15card, filelist[i + 1]);
break;
}
LOG_TEST_RET(card->ctx, r, "Error adding elements to framework");
if (r != SC_SUCCESS) {
sc_log(card->ctx, "Error %d adding elements to framework", r);
}
}
LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);

View File

@ -202,7 +202,7 @@ struct sc_pkcs15_prkey_dsa {
struct sc_pkcs15_ec_parameters {
char *named_curve;
struct sc_object_id id;
sc_pkcs15_der_t der;
struct sc_pkcs15_der der;
size_t field_length; /* in bits */
};
@ -214,13 +214,13 @@ struct sc_pkcs15_gost_parameters {
struct sc_pkcs15_pubkey_ec {
struct sc_pkcs15_ec_parameters params;
sc_pkcs15_der_t ecpointQ; /* note this is der */
struct sc_pkcs15_der ecpointQ; /* note this is der */
};
struct sc_pkcs15_prkey_ec {
struct sc_pkcs15_ec_parameters params;
sc_pkcs15_bignum_t privateD; /* note this is bignum */
sc_pkcs15_der_t ecpointQ; /* note this is der */
struct sc_pkcs15_der ecpointQ; /* note this is der */
};
struct sc_pkcs15_pubkey_gostr3410 {
@ -246,7 +246,7 @@ struct sc_pkcs15_pubkey {
} u;
/* DER encoded raw key */
sc_pkcs15_der_t data;
struct sc_pkcs15_der data;
};
typedef struct sc_pkcs15_pubkey sc_pkcs15_pubkey_t;
@ -300,7 +300,7 @@ struct sc_pkcs15_cert_info {
/* identifiers [2] SEQUENCE OF CredentialIdentifier{{KeyIdentifiers}} */
struct sc_path path;
sc_pkcs15_der_t value;
struct sc_pkcs15_der value;
};
typedef struct sc_pkcs15_cert_info sc_pkcs15_cert_info_t;
@ -320,6 +320,8 @@ struct sc_pkcs15_data_info {
struct sc_object_id app_oid;
struct sc_path path;
struct sc_pkcs15_der data;
};
typedef struct sc_pkcs15_data_info sc_pkcs15_data_info_t;
@ -618,7 +620,7 @@ typedef struct sc_pkcs15_card {
#define SC_PKCS15_TOKEN_PRN_GENERATION 0x04
#define SC_PKCS15_TOKEN_EID_COMPLIANT 0x08
/* flags suitable for sc_pkcs15_card_t */
/* flags suitable for struct sc_pkcs15_card */
#define SC_PKCS15_CARD_FLAG_EMULATED 0x02000000
/* sc_pkcs15_bind: Binds a card object to a PKCS #15 card object
@ -637,13 +639,13 @@ int sc_pkcs15_get_objects_cond(struct sc_pkcs15_card *card, unsigned int type,
int (* func)(struct sc_pkcs15_object *, void *),
void *func_arg,
struct sc_pkcs15_object **ret, size_t ret_count);
int sc_pkcs15_find_object_by_id(sc_pkcs15_card_t *, unsigned int,
int sc_pkcs15_find_object_by_id(struct sc_pkcs15_card *, unsigned int,
const sc_pkcs15_id_t *,
sc_pkcs15_object_t **);
struct sc_pkcs15_object **);
struct sc_pkcs15_card * sc_pkcs15_card_new(void);
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card);
void sc_pkcs15_card_clear(sc_pkcs15_card_t *p15card);
void sc_pkcs15_card_clear(struct sc_pkcs15_card *p15card);
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_object *prkey_obj,
@ -661,43 +663,39 @@ int sc_pkcs15_compute_signature(struct sc_pkcs15_card *p15card,
size_t inlen, u8 *out, size_t outlen);
int sc_pkcs15_read_pubkey(struct sc_pkcs15_card *,
const struct sc_pkcs15_object *,
struct sc_pkcs15_pubkey **);
const struct sc_pkcs15_object *, struct sc_pkcs15_pubkey **);
int sc_pkcs15_decode_pubkey_rsa(struct sc_context *,
struct sc_pkcs15_pubkey_rsa *,
const u8 *, size_t);
struct sc_pkcs15_pubkey_rsa *, const u8 *, size_t);
int sc_pkcs15_encode_pubkey_rsa(struct sc_context *,
struct sc_pkcs15_pubkey_rsa *, u8 **, size_t *);
struct sc_pkcs15_pubkey_rsa *, u8 **, size_t *);
int sc_pkcs15_decode_pubkey_dsa(struct sc_context *,
struct sc_pkcs15_pubkey_dsa *,
const u8 *, size_t);
struct sc_pkcs15_pubkey_dsa *, const u8 *, size_t);
int sc_pkcs15_encode_pubkey_dsa(struct sc_context *,
struct sc_pkcs15_pubkey_dsa *, u8 **, size_t *);
int sc_pkcs15_decode_pubkey_gostr3410(sc_context_t *,
struct sc_pkcs15_pubkey_dsa *, u8 **, size_t *);
int sc_pkcs15_decode_pubkey_gostr3410(struct sc_context *,
struct sc_pkcs15_pubkey_gostr3410 *, const u8 *, size_t);
int sc_pkcs15_encode_pubkey_gostr3410(sc_context_t *,
int sc_pkcs15_encode_pubkey_gostr3410(struct sc_context *,
struct sc_pkcs15_pubkey_gostr3410 *, u8 **, size_t *);
int sc_pkcs15_decode_pubkey_ec(struct sc_context *,
struct sc_pkcs15_pubkey_ec *, const u8 *, size_t);
struct sc_pkcs15_pubkey_ec *, const u8 *, size_t);
int sc_pkcs15_encode_pubkey_ec(struct sc_context *,
struct sc_pkcs15_pubkey_ec *, u8 **, size_t *);
struct sc_pkcs15_pubkey_ec *, u8 **, size_t *);
int sc_pkcs15_decode_pubkey(struct sc_context *,
struct sc_pkcs15_pubkey *, const u8 *, size_t);
struct sc_pkcs15_pubkey *, const u8 *, size_t);
int sc_pkcs15_encode_pubkey(struct sc_context *,
struct sc_pkcs15_pubkey *, u8 **, size_t *);
struct sc_pkcs15_pubkey *, u8 **, size_t *);
void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *);
void sc_pkcs15_free_pubkey(struct sc_pkcs15_pubkey *);
int sc_pkcs15_pubkey_from_prvkey(struct sc_context *, struct sc_pkcs15_prkey *,
struct sc_pkcs15_pubkey **);
struct sc_pkcs15_pubkey **);
int sc_pkcs15_pubkey_from_cert(struct sc_context *, struct sc_pkcs15_der *,
struct sc_pkcs15_pubkey **);
struct sc_pkcs15_pubkey **);
int sc_pkcs15_pubkey_from_spki_filename(struct sc_context *,
char *, sc_pkcs15_pubkey_t ** );
char *, struct sc_pkcs15_pubkey ** );
int sc_pkcs15_pubkey_from_spki(struct sc_context *,
sc_pkcs15_pubkey_t **, u8 *, size_t, int);
struct sc_pkcs15_pubkey **, u8 *, size_t, int);
int sc_pkcs15_encode_prkey(struct sc_context *,
struct sc_pkcs15_prkey *,
u8 **, size_t *);
struct sc_pkcs15_prkey *, u8 **, size_t *);
void sc_pkcs15_free_prkey(struct sc_pkcs15_prkey *prkey);
void sc_pkcs15_free_key_params(struct sc_pkcs15_key_params *params);
@ -738,9 +736,9 @@ int sc_pkcs15_find_prkey_by_id_usage(struct sc_pkcs15_card *card,
const struct sc_pkcs15_id *id,
unsigned int usage,
struct sc_pkcs15_object **out);
int sc_pkcs15_find_prkey_by_reference(sc_pkcs15_card_t *,
int sc_pkcs15_find_prkey_by_reference(struct sc_pkcs15_card *,
const sc_path_t *, int,
sc_pkcs15_object_t **);
struct sc_pkcs15_object **);
int sc_pkcs15_find_pubkey_by_id(struct sc_pkcs15_card *card,
const struct sc_pkcs15_id *id,
struct sc_pkcs15_object **out);
@ -778,13 +776,13 @@ int sc_pkcs15_find_pin_by_flags(struct sc_pkcs15_card *p15card,
void sc_pkcs15_pincache_add(struct sc_pkcs15_card *, struct sc_pkcs15_object *,
const u8 *, size_t);
int sc_pkcs15_pincache_revalidate(struct sc_pkcs15_card *p15card,
const sc_pkcs15_object_t *obj);
const struct sc_pkcs15_object *obj);
void sc_pkcs15_pincache_clear(struct sc_pkcs15_card *p15card);
int sc_pkcs15_encode_dir(struct sc_context *ctx,
struct sc_pkcs15_card *card,
u8 **buf, size_t *buflen);
int sc_pkcs15_parse_tokeninfo(sc_context_t *ctx,
int sc_pkcs15_parse_tokeninfo(struct sc_context *ctx,
sc_pkcs15_tokeninfo_t *ti,
const u8 *buf, size_t blen);
int sc_pkcs15_encode_tokeninfo(struct sc_context *ctx,
@ -853,7 +851,7 @@ int sc_pkcs15_add_unusedspace(struct sc_pkcs15_card *p15card,
const sc_path_t *path, const sc_pkcs15_id_t *auth_id);
int sc_pkcs15_parse_unusedspace(const u8 * buf, size_t buflen,
struct sc_pkcs15_card *card);
int sc_pkcs15_encode_unusedspace(sc_context_t *ctx,
int sc_pkcs15_encode_unusedspace(struct sc_context *ctx,
struct sc_pkcs15_card *p15card,
u8 **buf, size_t *buflen);
@ -866,7 +864,7 @@ void sc_pkcs15_free_pubkey_info(sc_pkcs15_pubkey_info_t *key);
void sc_pkcs15_free_cert_info(sc_pkcs15_cert_info_t *cert);
void sc_pkcs15_free_data_info(sc_pkcs15_data_info_t *data);
void sc_pkcs15_free_auth_info(sc_pkcs15_auth_info_t *auth_info);
void sc_pkcs15_free_object(sc_pkcs15_object_t *obj);
void sc_pkcs15_free_object(struct sc_pkcs15_object *obj);
/* Generic file i/o */
int sc_pkcs15_read_file(struct sc_pkcs15_card *p15card,
@ -887,7 +885,7 @@ int sc_pkcs15_compare_id(const struct sc_pkcs15_id *id1,
const char *sc_pkcs15_print_id(const struct sc_pkcs15_id *id);
void sc_pkcs15_format_id(const char *id_in, struct sc_pkcs15_id *id_out);
int sc_pkcs15_hex_string_to_id(const char *in, struct sc_pkcs15_id *out);
int sc_der_copy(sc_pkcs15_der_t *, const sc_pkcs15_der_t *);
int sc_der_copy(struct sc_pkcs15_der *, const struct sc_pkcs15_der *);
int sc_pkcs15_get_object_id(const struct sc_pkcs15_object *, struct sc_pkcs15_id *);
int sc_pkcs15_get_guid(struct sc_pkcs15_card *, const struct sc_pkcs15_object *, unsigned,
char *, size_t);
@ -940,8 +938,8 @@ typedef struct sc_pkcs15_search_key {
const char * label;
} sc_pkcs15_search_key_t;
int sc_pkcs15_search_objects(sc_pkcs15_card_t *, sc_pkcs15_search_key_t *,
sc_pkcs15_object_t **, size_t);
int sc_pkcs15_search_objects(struct sc_pkcs15_card *, sc_pkcs15_search_key_t *,
struct sc_pkcs15_object **, size_t);
/* This structure is passed to the new sc_pkcs15emu_*_init functions */
typedef struct sc_pkcs15emu_opt {
@ -951,26 +949,26 @@ typedef struct sc_pkcs15emu_opt {
#define SC_PKCS15EMU_FLAGS_NO_CHECK 0x00000001
extern int sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *);
extern int sc_pkcs15_bind_synthetic(struct sc_pkcs15_card *);
extern int sc_pkcs15_is_emulation_only(sc_card_t *);
int sc_pkcs15emu_object_add(sc_pkcs15_card_t *, unsigned int,
const sc_pkcs15_object_t *, const void *);
int sc_pkcs15emu_object_add(struct sc_pkcs15_card *, unsigned int,
const struct sc_pkcs15_object *, const void *);
/* some wrapper functions for sc_pkcs15emu_object_add */
int sc_pkcs15emu_add_pin_obj(sc_pkcs15_card_t *,
const sc_pkcs15_object_t *, const sc_pkcs15_auth_info_t *);
int sc_pkcs15emu_add_rsa_prkey(sc_pkcs15_card_t *,
const sc_pkcs15_object_t *, const sc_pkcs15_prkey_info_t *);
int sc_pkcs15emu_add_rsa_pubkey(sc_pkcs15_card_t *,
const sc_pkcs15_object_t *, const sc_pkcs15_pubkey_info_t *);
int sc_pkcs15emu_add_ec_prkey(sc_pkcs15_card_t *,
const sc_pkcs15_object_t *, const sc_pkcs15_prkey_info_t *);
int sc_pkcs15emu_add_ec_pubkey(sc_pkcs15_card_t *,
const sc_pkcs15_object_t *, const sc_pkcs15_pubkey_info_t *);
int sc_pkcs15emu_add_x509_cert(sc_pkcs15_card_t *,
const sc_pkcs15_object_t *, const sc_pkcs15_cert_info_t *);
int sc_pkcs15emu_add_data_object(sc_pkcs15_card_t *,
const sc_pkcs15_object_t *, const sc_pkcs15_data_info_t *);
int sc_pkcs15emu_add_pin_obj(struct sc_pkcs15_card *,
const struct sc_pkcs15_object *, const sc_pkcs15_auth_info_t *);
int sc_pkcs15emu_add_rsa_prkey(struct sc_pkcs15_card *,
const struct sc_pkcs15_object *, const sc_pkcs15_prkey_info_t *);
int sc_pkcs15emu_add_rsa_pubkey(struct sc_pkcs15_card *,
const struct sc_pkcs15_object *, const sc_pkcs15_pubkey_info_t *);
int sc_pkcs15emu_add_ec_prkey(struct sc_pkcs15_card *,
const struct sc_pkcs15_object *, const sc_pkcs15_prkey_info_t *);
int sc_pkcs15emu_add_ec_pubkey(struct sc_pkcs15_card *,
const struct sc_pkcs15_object *, const sc_pkcs15_pubkey_info_t *);
int sc_pkcs15emu_add_x509_cert(struct sc_pkcs15_card *,
const struct sc_pkcs15_object *, const sc_pkcs15_cert_info_t *);
int sc_pkcs15emu_add_data_object(struct sc_pkcs15_card *,
const struct sc_pkcs15_object *, const sc_pkcs15_data_info_t *);
#ifdef __cplusplus
}

View File

@ -2,7 +2,7 @@
* reader-pcsc.c: Reader driver for PC/SC interface
*
* Copyright (C) 2002 Juha Yrjölä <juha.yrjola@iki.fi>
* Copyright (C) 2009,2010 Martin Paljak <martin@paljak.pri.ee>
* Copyright (C) 2009,2010 Martin Paljak <martin@martinpaljak.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@ -518,6 +518,8 @@ void sc_file_free(sc_file_t *file)
free(file->prop_attr);
if (file->type_attr)
free(file->type_attr);
if (file->encoded_content)
free(file->encoded_content);
free(file);
}

179
src/libopensc/sm.c Normal file
View File

@ -0,0 +1,179 @@
/*
* sm.c: Secure Messaging helper functions
*
* Copyright (C) 2013 Viktor Tarasov <viktor.tarasov@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "internal.h"
#include "asn1.h"
static const struct sc_asn1_entry c_asn1_sm_response[4] = {
{ "encryptedData", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 7, SC_ASN1_OPTIONAL, NULL, NULL },
{ "statusWord", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 0x19, 0, NULL, NULL },
{ "mac", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 0x0E, 0, NULL, NULL },
{ NULL, 0, 0, 0, NULL, NULL }
};
#ifdef ENABLE_SM
int
sc_sm_parse_answer(struct sc_card *card, unsigned char *resp_data, size_t resp_len,
struct sm_card_response *out)
{
struct sc_asn1_entry asn1_sm_response[4];
unsigned char data[SC_MAX_APDU_BUFFER_SIZE];
size_t data_len = sizeof(data);
unsigned char status[2] = {0, 0};
size_t status_len = sizeof(status);
unsigned char mac[8];
size_t mac_len = sizeof(mac);
int rv;
if (!resp_data || !resp_len || !out)
return SC_ERROR_INVALID_ARGUMENTS;
sc_copy_asn1_entry(c_asn1_sm_response, asn1_sm_response);
sc_format_asn1_entry(asn1_sm_response + 0, data, &data_len, 0);
sc_format_asn1_entry(asn1_sm_response + 1, status, &status_len, 0);
sc_format_asn1_entry(asn1_sm_response + 2, mac, &mac_len, 0);
rv = sc_asn1_decode(card->ctx, asn1_sm_response, resp_data, resp_len, NULL, NULL);
if (rv)
return rv;
if (asn1_sm_response[0].flags & SC_ASN1_PRESENT) {
if (data_len > sizeof(out->data))
return SC_ERROR_BUFFER_TOO_SMALL;
memcpy(out->data, data, data_len);
out->data_len = data_len;
}
if (asn1_sm_response[1].flags & SC_ASN1_PRESENT) {
if (!status[0])
return SC_ERROR_INVALID_DATA;
out->sw1 = status[0];
out->sw2 = status[1];
}
if (asn1_sm_response[2].flags & SC_ASN1_PRESENT) {
memcpy(out->mac, mac, mac_len);
out->mac_len = mac_len;
}
return SC_SUCCESS;
}
/** parse answer of SM protected APDU returned by APDU or by 'GET RESPONSE'
* @param card 'sc_card' smartcard object
* @param resp_data 'raw data returned by SM protected APDU
* @param resp_len 'length of raw data returned by SM protected APDU
* @param ref_rv 'status word returned by APDU or 'GET RESPONSE' (can be different from status word encoded into SM response date)
* @param apdu 'sc_apdu' object to update
* @return SC_SUCCESS on success and an error code otherwise
*/
int
sc_sm_update_apdu_response(struct sc_card *card, unsigned char *resp_data, size_t resp_len,
int ref_rv, struct sc_apdu *apdu)
{
struct sm_card_response sm_resp;
int r;
if (!apdu)
return SC_ERROR_INVALID_ARGUMENTS;
else if (!resp_data || !resp_len)
return SC_SUCCESS;
memset(&sm_resp, 0, sizeof(sm_resp));
r = sc_sm_parse_answer(card, resp_data, resp_len, &sm_resp);
if (r)
return r;
if (sm_resp.mac_len) {
if (sm_resp.mac_len > sizeof(apdu->mac))
return SC_ERROR_INVALID_DATA;
memcpy(apdu->mac, sm_resp.mac, sm_resp.mac_len);
apdu->mac_len = sm_resp.mac_len;
}
apdu->sw1 = sm_resp.sw1;
apdu->sw2 = sm_resp.sw2;
return SC_SUCCESS;
}
int
sc_sm_single_transmit(struct sc_card *card, struct sc_apdu *apdu)
{
struct sc_context *ctx = card->ctx;
struct sc_apdu *sm_apdu = NULL;
int rv;
LOG_FUNC_CALLED(ctx);
sc_log(ctx, "SM_MODE:%X", card->sm_ctx.sm_mode);
if (!card->sm_ctx.ops.get_sm_apdu || !card->sm_ctx.ops.free_sm_apdu)
LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
/* get SM encoded APDU */
rv = card->sm_ctx.ops.get_sm_apdu(card, apdu, &sm_apdu);
if (rv == SC_ERROR_SM_NOT_APPLIED) {
/* SM wrap of this APDU is ignored by card driver.
* Send plain APDU to the reader driver */
rv = card->reader->ops->transmit(card->reader, apdu);
LOG_FUNC_RETURN(ctx, rv);
}
LOG_TEST_RET(ctx, rv, "get SM APDU error");
/* check if SM APDU is still valid */
rv = sc_check_apdu(card, sm_apdu);
if (rv < 0) {
card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu);
LOG_TEST_RET(ctx, rv, "cannot validate SM encoded APDU");
}
/* send APDU to the reader driver */
rv = card->reader->ops->transmit(card->reader, sm_apdu);
LOG_TEST_RET(ctx, rv, "unable to transmit APDU");
/* decode SM answer and free temporary SM related data */
rv = card->sm_ctx.ops.free_sm_apdu(card, apdu, &sm_apdu);
LOG_FUNC_RETURN(ctx, rv);
}
#else
int
sc_sm_parse_answer(struct sc_context *ctx, unsigned char *resp_data, size_t resp_len,
struct sm_card_response *out)
{
return SC_ERROR_NOT_SUPPORTED;
}
int
sc_sm_update_apdu_response(struct sc_card *card, unsigned char *resp_data, size_t resp_len, int ref_rv,
struct sc_apdu *apdu)
{
return SC_ERROR_NOT_SUPPORTED;
}
int
sc_sm_single_transmit(struct sc_card *card, struct sc_apdu *apdu)
{
return SC_ERROR_NOT_SUPPORTED;
}
#endif

View File

@ -43,21 +43,22 @@ extern "C" {
#define SM_TYPE_GP_SCP01 0x100
#define SM_TYPE_CWA14890 0x400
#define SM_TYPE_DH_RSA 0x500
#define SM_MODE_NONE 0x0
#define SM_MODE_ACL 0x100
#define SM_MODE_TRANSMIT 0x200
#define SM_CMD_INITIALIZE 0x10
#define SM_CMD_INITIALIZE 0x10
#define SM_CMD_MUTUAL_AUTHENTICATION 0x20
#define SM_CMD_RSA 0x100
#define SM_CMD_RSA_GENERATE 0x101
#define SM_CMD_RSA 0x100
#define SM_CMD_RSA_GENERATE 0x101
#define SM_CMD_RSA_UPDATE 0x102
#define SM_CMD_RSA_READ_PUBLIC 0x103
#define SM_CMD_RSA_READ_PUBLIC 0x103
#define SM_CMD_FILE 0x200
#define SM_CMD_FILE_READ 0x201
#define SM_CMD_FILE_UPDATE 0x202
#define SM_CMD_FILE_CREATE 0x203
#define SM_CMD_FILE_UPDATE 0x202
#define SM_CMD_FILE_CREATE 0x203
#define SM_CMD_FILE_DELETE 0x204
#define SM_CMD_PIN 0x300
#define SM_CMD_PIN_VERIFY 0x301
@ -200,6 +201,26 @@ struct sm_cwa_session {
size_t mdata_len;
};
/*
* @struct sm_dh_session
* DH SM session data:
*/
struct sm_dh_session {
struct sc_tlv_data g;
struct sc_tlv_data N;
struct sc_tlv_data ifd_p;
struct sc_tlv_data ifd_y;
struct sc_tlv_data icc_p;
struct sc_tlv_data shared_secret;
unsigned char session_enc[16];
unsigned char session_mac[16];
unsigned char card_challenge[32];
unsigned char ssc[8];
};
/*
* @struct sc_info is the
* placehold for the secure messaging working data:
@ -219,6 +240,7 @@ struct sm_info {
union {
struct sm_gp_session gp;
struct sm_cwa_session cwa;
struct sm_dh_session dh;
} session;
struct sc_serial_number serialnr;
@ -329,6 +351,10 @@ typedef struct sm_context {
int iasecc_sm_external_authentication(struct sc_card *, unsigned, int *);
int sc_sm_parse_answer(struct sc_card *, unsigned char *, size_t, struct sm_card_response *);
int sc_sm_update_apdu_response(struct sc_card *, unsigned char *, size_t, int, struct sc_apdu *);
int sc_sm_single_transmit(struct sc_card *, struct sc_apdu *);
#ifdef __cplusplus
}
#endif

View File

@ -174,8 +174,11 @@ struct sc_crt {
#define SC_AC_OP_WRITE 24
#define SC_AC_OP_RESIZE 25
#define SC_AC_OP_GENERATE 26
#define SC_AC_OP_CREATE_EF 27
#define SC_AC_OP_CREATE_DF 28
#define SC_AC_OP_ADMIN 29
/* If you add more OPs here, make sure you increase SC_MAX_AC_OPS*/
#define SC_MAX_AC_OPS 27
#define SC_MAX_AC_OPS 30
/* the use of SC_AC_OP_ERASE is deprecated, SC_AC_OP_DELETE should be used
* instead */
@ -215,7 +218,7 @@ typedef struct sc_acl_entry {
(at least for SetCOS 4.4 */
typedef struct sc_file {
struct sc_path path;
u8 name[16]; /* DF name */
unsigned char name[16]; /* DF name */
size_t namelen; /* length of DF name */
unsigned int type, ef_structure, status; /* See constant values defined above */
@ -227,13 +230,19 @@ typedef struct sc_file {
int record_length; /* In case of fixed-length or cyclic EF */
int record_count; /* Valid, if not transparent EF or DF */
u8 *sec_attr;
unsigned char *sec_attr; /* security data in proprietary format. tag '86' */
size_t sec_attr_len;
u8 *prop_attr;
unsigned char *prop_attr; /* proprietary information. tag '85'*/
size_t prop_attr_len;
u8 *type_attr;
unsigned char *type_attr; /* file descriptor data. tag '82'.
replaces the file's type information (DF, EF, ...) */
size_t type_attr_len;
unsigned char *encoded_content; /* file's content encoded to be used in the file creation command */
size_t encoded_content_len; /* size of file's encoded content in bytes */
unsigned int magic;
} sc_file_t;
@ -263,18 +272,23 @@ typedef struct sc_file {
*/
#define SC_APDU_FLAGS_NO_RETRY_WL 0x00000004UL
typedef struct sc_apdu {
int cse; /* APDU case */
u8 cla, ins, p1, p2; /* CLA, INS, P1 and P2 bytes */
size_t lc, le; /* Lc and Le bytes */
const u8 *data; /* C-APDU data */
size_t datalen; /* length of data in C-APDU */
u8 *resp; /* R-APDU data buffer */
size_t resplen; /* in: size of R-APDU buffer,
* out: length of data returned in R-APDU */
u8 control; /* Set if APDU should go to the reader */
#define SC_APDU_ALLOCATE_FLAG 0x01
#define SC_APDU_ALLOCATE_FLAG_DATA 0x02
#define SC_APDU_ALLOCATE_FLAG_RESP 0x04
unsigned int sw1, sw2; /* Status words returned in R-APDU */
typedef struct sc_apdu {
int cse; /* APDU case */
unsigned char cla, ins, p1, p2; /* CLA, INS, P1 and P2 bytes */
size_t lc, le; /* Lc and Le bytes */
unsigned char *data; /* C-APDU data */
size_t datalen; /* length of data in C-APDU */
unsigned char *resp; /* R-APDU data buffer */
size_t resplen; /* in: size of R-APDU buffer,
* out: length of data returned in R-APDU */
unsigned char control; /* Set if APDU should go to the reader */
unsigned allocation_flags; /* APDU allocation flags */
unsigned int sw1, sw2; /* Status words returned in R-APDU */
unsigned char mac[8];
size_t mac_len;

12
src/libsm/Makefile.am Normal file
View File

@ -0,0 +1,12 @@
# Process this file with automake to create Makefile.in
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = Makefile.mak
noinst_LTLIBRARIES = libsm.la
noinst_HEADERS = sm-common.h
AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(OPTIONAL_READLINE_CFLAGS)
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src/include
libsm_la_SOURCES = sm-common.c sm-common.h

11
src/libsm/Makefile.mak Normal file
View File

@ -0,0 +1,11 @@
TOPDIR = ..\..
TARGET = libsm.lib
OBJECTS = sm-common.obj
all: $(TARGET)
$(TARGET): $(OBJECTS)
lib $(LIBFLAGS) /out:$(TARGET) $(OBJECTS)
!INCLUDE $(TOPDIR)\win32\Make.rules.mak

View File

@ -1,6 +1,6 @@
/*
* sm-common.c: Common cryptographic procedures related to
* Secure Messaging
* Secure Messaging
*
* Copyright (C) 2010 Viktor Tarasov <vtarasov@opentrust.com>
* OpenTrust <www.opentrust.com>
@ -47,7 +47,7 @@
#include "libopensc/asn1.h"
#include "libopensc/log.h"
#include "sm-module.h"
#include "sm-common.h"
/*
* From crypto/des/des_locl.h of OpenSSL .
@ -98,11 +98,11 @@ DES_3cbc_encrypt(DES_cblock *input, DES_cblock *output, long length,
(unsigned char*)output,l8,ks2,iv,!enc);
DES_cbc_encrypt((unsigned char*)output,
(unsigned char*)output,l8,ks1,iv,enc);
if (length >= sizeof(DES_cblock))
if ((unsigned)length >= sizeof(DES_cblock))
memcpy(icv_out,output[off],sizeof(DES_cblock));
}
else {
if (length >= sizeof(DES_cblock))
if ((unsigned)length >= sizeof(DES_cblock))
memcpy(icv_out,input[off],sizeof(DES_cblock));
DES_cbc_encrypt((unsigned char*)input,
(unsigned char*)output,l8,ks1,iv,enc);
@ -326,14 +326,8 @@ sm_encrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
memcpy(data, in, in_len);
memcpy(data + in_len, "\x80\0\0\0\0\0\0\0", 8);
if (not_force_pad) {
data_len = in_len + 7;
data_len -= (data_len%8);
}
else {
data_len = in_len + 8;
data_len -= (data_len%8);
}
data_len = in_len + (not_force_pad ? 7 : 8);
data_len -= (data_len%8);
sc_log(ctx, "SM encrypt_des_cbc3: data to encrypt (len:%i,%s)", data_len, sc_dump_hex(data, data_len));
*out_len = data_len;
@ -353,3 +347,19 @@ sm_encrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
free(data);
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}
void
sm_incr_ssc(unsigned char *ssc, size_t ssc_len)
{
int ii;
if (!ssc)
return;
for (ii = ssc_len - 1;ii >= 0; ii++) {
*(ssc + ii) += 1;
if (*(ssc + ii) != 0)
break;
}
}

52
src/libsm/sm-common.h Normal file
View File

@ -0,0 +1,52 @@
/*
* sm-commot.h: Common SM cryptographic procedures
*
* Copyright (C) 2013 Viktor Tarasov <viktor.tarasov@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _SM_COMMON_H
#define _SM_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
#include <openssl/des.h>
#include <openssl/sha.h>
#include "libopensc/sm.h"
DES_LONG DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output, long length,
DES_key_schedule *schedule, DES_key_schedule *schedule2, const_DES_cblock *ivec);
DES_LONG DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output,
long length, DES_key_schedule *schedule, DES_key_schedule *schedule2,
const_DES_cblock *ivec);
int sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len,
unsigned char **out, int *out_len);
int sm_encrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
const unsigned char *in, size_t in_len,
unsigned char **out, size_t *out_len, int
not_force_pad);
int sm_decrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
unsigned char *data, size_t data_len, unsigned char **out, size_t *out_len);
void sm_incr_ssc(unsigned char *ssc, size_t ssc_len);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -2694,19 +2694,35 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
}
if (alg_info->flags & SC_ALGORITHM_RSA_RAW) {
logprintf(pCardData, 2, "sc_pkcs15_decipher: using RSA-RAW mechanism\n");
r = sc_pkcs15_decipher(vs->p15card, pkey, opt_crypt_flags, pbuf, pInfo->cbData, pbuf2, pInfo->cbData);
if (r < 0) {
logprintf(pCardData, 2, "PKCS#15 decipher failed: %i\n", r);
return SCARD_F_INTERNAL_ERROR;
}
logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r);
// Need to handle padding
if (pInfo->dwVersion >= CARD_RSA_KEY_DECRYPT_INFO_VERSION_TWO) {
if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) {
r = sc_pkcs1_strip_02_padding(pbuf2, pInfo->cbData,
pbuf2, &pInfo->cbData);
logprintf(pCardData, 2, "sc_pkcs15_decipher: DECRYPT-INFO dwVersion=%u\n", pInfo->dwVersion);
if (pInfo->dwPaddingType == CARD_PADDING_PKCS1) {
logprintf(pCardData, 2, "sc_pkcs15_decipher: stripping PKCS1 padding\n");
r = sc_pkcs1_strip_02_padding(vs->ctx, pbuf2, pInfo->cbData, pbuf2, &pInfo->cbData);
if (r < 0) {
logprintf(pCardData, 2, "Cannot strip PKCS1 padding: %i\n", r);
return SCARD_F_INTERNAL_ERROR;
}
pInfo->cbData = r;
}
else if (pInfo->dwPaddingType == CARD_PADDING_OAEP) {
/* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */
logprintf(pCardData, 2, "OAEP padding not implemented\n");
return SCARD_F_INTERNAL_ERROR;
}
/* TODO: Handle OAEP padding if present - can call PFN_CSP_UNPAD_DATA */
}
}
else if (alg_info->flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
logprintf(pCardData, 2, "sc_pkcs15_decipher: no oncard RSA RAW mechanism, try to use with PAD_PKCS1\n");
logprintf(pCardData, 2, "sc_pkcs15_decipher: using RSA_PAD_PKCS1 mechanism\n");
r = sc_pkcs15_decipher(vs->p15card, pkey, opt_crypt_flags | SC_ALGORITHM_RSA_PAD_PKCS1,
pbuf, pInfo->cbData, pbuf2, pInfo->cbData);
logprintf(pCardData, 2, "sc_pkcs15_decipher returned %d\n", r);
@ -2739,7 +2755,7 @@ DWORD WINAPI CardRSADecrypt(__in PCARD_DATA pCardData,
}
if ( r < 0) {
logprintf(pCardData, 2, "sc_pkcs15_decipher erreur %s\n", sc_strerror(r));
logprintf(pCardData, 2, "sc_pkcs15_decipher error(%i): %s\n", r, sc_strerror(r));
return SCARD_E_INVALID_VALUE;
}

View File

@ -157,7 +157,6 @@ static CK_RV get_modulus(struct sc_pkcs15_pubkey *,
static CK_RV get_modulus_bits(struct sc_pkcs15_pubkey *,
CK_ATTRIBUTE_PTR);
static CK_RV get_usage_bit(unsigned int usage, CK_ATTRIBUTE_PTR attr);
static CK_RV asn1_sequence_wrapper(const u8 *, size_t, CK_ATTRIBUTE_PTR);
static CK_RV get_gostr3410_params(const u8 *, size_t, CK_ATTRIBUTE_PTR);
static CK_RV get_ec_pubkey_point(struct sc_pkcs15_pubkey *, CK_ATTRIBUTE_PTR);
static CK_RV get_ec_pubkey_params(struct sc_pkcs15_pubkey *, CK_ATTRIBUTE_PTR);
@ -187,8 +186,8 @@ get_fw_data(struct sc_pkcs11_card *p11card, struct sc_app_info *app_info, int *o
if (!fw_data || !fw_data->p15_card)
continue;
if (app_info) {
file_app = fw_data->p15_card->file_app;
file_app = fw_data->p15_card->file_app;
if (app_info && file_app) {
if (file_app->path.len != app_info->path.len)
continue;
if (file_app->path.aid.len != app_info->path.aid.len)
@ -3037,13 +3036,17 @@ pkcs15_cert_get_attribute(struct sc_pkcs11_session *session, void *object, CK_AT
attr->ulValueLen = 0;
return CKR_OK;
}
return asn1_sequence_wrapper(cert->cert_data->subject, cert->cert_data->subject_len, attr);
check_attribute_buffer(attr, cert->cert_data->subject_len);
memcpy(attr->pValue, cert->cert_data->subject, cert->cert_data->subject_len);
return CKR_OK;
case CKA_ISSUER:
if (check_cert_data_read(fw_data, cert) != 0) {
attr->ulValueLen = 0;
return CKR_OK;
}
return asn1_sequence_wrapper(cert->cert_data->issuer, cert->cert_data->issuer_len, attr);
check_attribute_buffer(attr, cert->cert_data->issuer_len);
memcpy(attr->pValue, cert->cert_data->issuer, cert->cert_data->issuer_len);
return CKR_OK;
default:
return CKR_ATTRIBUTE_TYPE_INVALID;
}
@ -4052,13 +4055,12 @@ static int pkcs15_skey_get_value(struct sc_pkcs11_session *session,
* but for now we only work with session objects
* derived from other keys
*/
skey_data= malloc(sizeof(struct sc_pkcs15_skey));
skey_data= calloc(1, sizeof(struct sc_pkcs15_skey));
if (skey_data == NULL)
return SC_ERROR_OUT_OF_MEMORY;
memset(skey_data, 0, sizeof(struct sc_pkcs15_skey));
if (skey->value && skey->value->data_len) {
skey_data->data = malloc(skey_data->data_len);
skey_data->data = calloc(1, skey_data->data_len);
if (skey_data->data == NULL) {
free(skey_data);
return SC_ERROR_OUT_OF_MEMORY;
@ -4324,42 +4326,8 @@ get_usage_bit(unsigned int usage, CK_ATTRIBUTE_PTR attr)
}
static CK_RV
asn1_sequence_wrapper(const u8 *data, size_t len, CK_ATTRIBUTE_PTR attr)
{
u8 *dest;
unsigned int n;
size_t len2;
size_t lenb = 1;
len2 = len;
/* calculate the number of bytes needed for the length */
if (len > 127) {
unsigned int i;
for (i = 0; (len & (0xff << i)) != 0 && (0xff << i) != 0; i++)
lenb++;
}
check_attribute_buffer(attr, 1 + lenb + len);
dest = (u8 *) attr->pValue;
*dest++ = 0x30; /* SEQUENCE tag */
if (len <= 127) {
*dest++ = len;
} else {
for (n = 4; (len & 0xFF000000) == 0; n--)
len <<= 8;
*dest++ = 0x80 + n;
while (n--) {
*dest++ = len >> 24;
len <<= 8;
}
}
memcpy(dest, data, len2);
attr->ulValueLen = (dest - (u8 *) attr->pValue) + len2;
return CKR_OK;
}
static int register_gost_mechanisms(struct sc_pkcs11_card *p11card, int flags)
static int
register_gost_mechanisms(struct sc_pkcs11_card *p11card, int flags)
{
CK_MECHANISM_INFO mech_info;
sc_pkcs11_mechanism_type_t *mt;

View File

@ -673,7 +673,7 @@ sc_pkcs11_verify_final(sc_pkcs11_operation_t *operation,
rv = key->ops->get_attribute(operation->session, key, &attr);
if (rv != CKR_OK)
return rv;
pubkey_value = malloc(attr.ulValueLen);
pubkey_value = calloc(1, attr.ulValueLen);
attr.pValue = pubkey_value;
rv = key->ops->get_attribute(operation->session, key, &attr);
if (rv != CKR_OK)

View File

@ -420,7 +420,7 @@ CK_RV sc_pkcs11_verify_data(const unsigned char *pubkey, int pubkey_len,
if (rsa == NULL)
return CKR_DEVICE_MEMORY;
rsa_out = malloc(RSA_size(rsa));
rsa_out = calloc(1, RSA_size(rsa));
if (rsa_out == NULL) {
RSA_free(rsa);
return CKR_DEVICE_MEMORY;

View File

@ -42,7 +42,7 @@ extern CK_FUNCTION_LIST pkcs11_function_list;
#include <pthread.h>
CK_RV mutex_create(void **mutex)
{
pthread_mutex_t *m = malloc(sizeof(*mutex));
pthread_mutex_t *m = calloc(1, sizeof(*mutex));
if (m == NULL)
return CKR_GENERAL_ERROR;;
pthread_mutex_init(m, NULL);
@ -80,7 +80,7 @@ CK_RV mutex_create(void **mutex)
{
CRITICAL_SECTION *m;
m = malloc(sizeof(*m));
m = calloc(1, sizeof(*m));
if (m == NULL)
return CKR_GENERAL_ERROR;
InitializeCriticalSection(m);
@ -243,15 +243,12 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
if (sc_pkcs11_conf.plug_and_play) {
create_slot(NULL);
}
/* Create slots for readers found on initialization */
for (i=0; i<sc_ctx_get_reader_count(context); i++) {
initialize_reader(sc_ctx_get_reader(context, i));
}
/* Set initial event state on slots */
for (i=0; i<list_size(&virtual_slots); i++) {
sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
slot->events = 0; /* Initially there are no events */
/* Create slots for readers found on initialization, only if in 2.11 mode */
if (!sc_pkcs11_conf.plug_and_play) {
for (i=0; i<sc_ctx_get_reader_count(context); i++) {
initialize_reader(sc_ctx_get_reader(context, i));
}
}
out:
@ -330,7 +327,11 @@ CK_RV C_GetInfo(CK_INFO_PTR pInfo)
memset(pInfo, 0, sizeof(CK_INFO));
pInfo->cryptokiVersion.major = 2;
pInfo->cryptokiVersion.minor = 20;
if (sc_pkcs11_conf.plug_and_play) {
pInfo->cryptokiVersion.minor = 20;
} else {
pInfo->cryptokiVersion.minor = 11;
}
strcpy_bp(pInfo->manufacturerID,
"OpenSC (www.opensc-project.org)",
sizeof(pInfo->manufacturerID));
@ -384,7 +385,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese
card_detect_all();
found = malloc(list_size(&virtual_slots) * sizeof(CK_SLOT_ID));
found = calloc(list_size(&virtual_slots), sizeof(CK_SLOT_ID));
if (found == NULL) {
rv = CKR_HOST_MEMORY;

View File

@ -1352,7 +1352,7 @@ int sc_pkcs11_any_cmp_attribute(struct sc_pkcs11_session *session, void *ptr, CK
if (temp_attr.ulValueLen <= sizeof(temp1))
temp_attr.pValue = temp1;
else {
temp2 = malloc(temp_attr.ulValueLen);
temp2 = calloc(1, temp_attr.ulValueLen);
if (temp2 == NULL)
return 0;
temp_attr.pValue = temp2;

View File

@ -23,10 +23,6 @@
#include "config.h"
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#include "libopensc/opensc.h"
#include "libopensc/pkcs15.h"
#include "libopensc/log.h"

View File

@ -2,7 +2,7 @@
* slot.c: reader, smart card and slot related management functions
*
* Copyright (C) 2002 Timo Teräs <timo.teras@iki.fi>
* Copyright (C) 2009 Martin Paljak <martin@paljak.pri.ee>
* Copyright (C) 2009 Martin Paljak <martin@martinpaljak.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@ -201,7 +201,7 @@ filesystem {
acl = READ=$PIN, UPDATE=$PIN, DELETE=$PIN;
}
EF data {
file-id = 4501;
file-id = 4601;
structure = transparent;
acl = READ=NONE, UPDATE=$PIN, DELETE=$PIN;
}

View File

@ -170,8 +170,6 @@ cardos_select_pin_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card,
/* PINs are even numbered, PUKs are odd */
if (!(preferred & 1))
preferred++;
if (preferred >= 126)
return SC_ERROR_TOO_MANY_OBJECTS;
}
if (current > preferred || preferred > CARDOS_PIN_ID_MAX)

View File

@ -507,6 +507,12 @@ static int epass2003_pkcs15_generate_key(struct sc_profile *profile,
sc_print_path(&file->path));
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "private key_info path: %s",
sc_print_path(&(key_info->path)));
r = sc_pkcs15init_authenticate(profile, p15card, file,
SC_AC_OP_DELETE);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r,
"generate key: pkcs15init_authenticate(SC_AC_OP_DELETE) failed");
r = sc_delete_file(p15card->card, &file->path);
/* create */
r = sc_pkcs15init_create_file(profile, p15card, file);
@ -558,6 +564,11 @@ static int epass2003_pkcs15_generate_key(struct sc_profile *profile,
r = sc_select_file(p15card->card, &pukf->path, NULL);
/* if exist, delete */
if (r == SC_SUCCESS) {
r = sc_pkcs15init_authenticate(profile, p15card, pukf,
SC_AC_OP_DELETE);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r,
"generate key - pubkey: pkcs15init_authenticate(SC_AC_OP_DELETE) failed");
r = sc_pkcs15init_delete_by_path(profile, p15card, &pukf->path);
if (r != SC_SUCCESS) {
sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
@ -573,6 +584,11 @@ static int epass2003_pkcs15_generate_key(struct sc_profile *profile,
goto failed;
}
r = sc_pkcs15init_authenticate(profile, p15card, pukf,
SC_AC_OP_UPDATE);
SC_TEST_RET(card->ctx, SC_LOG_DEBUG_NORMAL, r,
"generate key - pubkey: pkcs15init_authenticate(SC_AC_OP_UPDATE) failed");
/* generate key pair */
fidl = (file->id & 0xff) * FID_STEP;
file->id = (file->id & 0xff00) + fidl;

View File

@ -415,7 +415,7 @@ iasecc_sdo_set_key_acls_from_profile(struct sc_profile *profile, struct sc_card
sdo->docp.acls_contact.size = cntr + 1;
sdo->docp.acls_contact.value = calloc(1, sdo->docp.acls_contact.size);
if (!sdo->docp.acls_contact.value)
return SC_ERROR_MEMORY_FAILURE;
return SC_ERROR_OUT_OF_MEMORY;
*(sdo->docp.acls_contact.value + 0) = amb;
memcpy(sdo->docp.acls_contact.value + 1, scb, cntr);
@ -438,7 +438,7 @@ iasecc_sdo_allocate_prvkey(struct sc_profile *profile, struct sc_card *card,
sdo = calloc(1, sizeof(struct iasecc_sdo));
if (!sdo)
LOG_TEST_RET(ctx, SC_ERROR_MEMORY_FAILURE, "Cannot allocate 'iasecc_sdo'");
LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate 'iasecc_sdo'");
sdo->magic = SC_CARDCTL_IASECC_SDO_MAGIC;
sdo->sdo_ref = key_info->key_reference & 0x3F;
@ -458,19 +458,19 @@ iasecc_sdo_allocate_prvkey(struct sc_profile *profile, struct sc_card *card,
sdo->docp.non_repudiation.value = calloc(1, 1);
if (!sdo->docp.non_repudiation.value)
LOG_FUNC_RETURN(ctx, SC_ERROR_MEMORY_FAILURE);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
sdo->docp.non_repudiation.tag = IASECC_DOCP_TAG_NON_REPUDATION;
sdo->docp.non_repudiation.size = 1;
sdo->data.prv_key.compulsory.value = calloc(1, 1);
if (!sdo->data.prv_key.compulsory.value)
LOG_FUNC_RETURN(ctx, SC_ERROR_MEMORY_FAILURE);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
sdo->data.prv_key.compulsory.tag = IASECC_SDO_PRVKEY_TAG_COMPULSORY;
sdo->data.prv_key.compulsory.size = 1;
sdo->docp.size.value = calloc(1, 2);
if (!sdo->docp.size.value)
LOG_FUNC_RETURN(ctx, SC_ERROR_MEMORY_FAILURE);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
sdo->docp.size.tag = IASECC_DOCP_TAG_SIZE;
sdo->docp.size.size = 2;
*(sdo->docp.size.value + 0) = (sz >> 8) & 0xFF;
@ -517,7 +517,7 @@ iasecc_sdo_allocate_pubkey(struct sc_profile *profile, struct sc_card *card, str
LOG_FUNC_CALLED(ctx);
sdo = calloc(1, sizeof(struct iasecc_sdo));
if (!sdo)
return SC_ERROR_MEMORY_FAILURE;
return SC_ERROR_OUT_OF_MEMORY;
sdo->magic = SC_CARDCTL_IASECC_SDO_MAGIC;
sdo->sdo_ref = key_info->key_reference & 0x3F;
@ -533,7 +533,7 @@ iasecc_sdo_allocate_pubkey(struct sc_profile *profile, struct sc_card *card, str
sdo->docp.size.value = calloc(1, 2);
if (!sdo->docp.size.value)
LOG_FUNC_RETURN(ctx, SC_ERROR_MEMORY_FAILURE);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
sdo->docp.size.size = 2;
sdo->docp.size.tag = IASECC_DOCP_TAG_SIZE;
*(sdo->docp.size.value + 0) = (sz >> 8) & 0xFF;
@ -545,14 +545,14 @@ iasecc_sdo_allocate_pubkey(struct sc_profile *profile, struct sc_card *card, str
else {
sdo->data.pub_key.cha.value = calloc(1, 2);
if (!sdo->data.pub_key.cha.value)
LOG_FUNC_RETURN(ctx, SC_ERROR_MEMORY_FAILURE);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
sdo->data.pub_key.cha.size = 2;
sdo->data.pub_key.cha.tag = IASECC_SDO_PUBKEY_TAG_CHA;
}
sdo->data.pub_key.compulsory.value = calloc(1, 1);
if (!sdo->data.pub_key.compulsory.value)
LOG_FUNC_RETURN(ctx, SC_ERROR_MEMORY_FAILURE);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
sdo->data.pub_key.compulsory.tag = IASECC_SDO_PUBKEY_TAG_COMPULSORY;
sdo->data.pub_key.compulsory.size = 1;
}
@ -1137,13 +1137,13 @@ iasecc_pkcs15_generate_key(struct sc_profile *profile, sc_pkcs15_card_t *p15card
pubkey->u.rsa.modulus.len = sdo_pubkey->data.pub_key.n.size;
pubkey->u.rsa.modulus.data = (unsigned char *) malloc(pubkey->u.rsa.modulus.len);
if (!pubkey->u.rsa.modulus.data)
LOG_FUNC_RETURN(ctx, SC_ERROR_MEMORY_FAILURE);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
memcpy(pubkey->u.rsa.modulus.data, sdo_pubkey->data.pub_key.n.value, pubkey->u.rsa.modulus.len);
pubkey->u.rsa.exponent.len = sdo_pubkey->data.pub_key.e.size;
pubkey->u.rsa.exponent.data = (unsigned char *) malloc(pubkey->u.rsa.exponent.len);
if (!pubkey->u.rsa.exponent.data)
LOG_FUNC_RETURN(ctx, SC_ERROR_MEMORY_FAILURE);
LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
memcpy(pubkey->u.rsa.exponent.data, sdo_pubkey->data.pub_key.e.value, pubkey->u.rsa.exponent.len);
rv = sc_pkcs15_encode_pubkey(ctx, pubkey, &pubkey->data.value, &pubkey->data.len);
@ -1236,7 +1236,7 @@ iasecc_pkcs15_delete_sdo (struct sc_profile *profile, struct sc_pkcs15_card *p15
sdo = calloc(1, sizeof(struct iasecc_sdo));
if (!sdo)
return SC_ERROR_MEMORY_FAILURE;
return SC_ERROR_OUT_OF_MEMORY;
sdo->magic = SC_CARDCTL_IASECC_SDO_MAGIC;
sdo->sdo_class = sdo_class;

View File

@ -189,8 +189,6 @@ incrypto34_select_pin_reference(sc_profile_t *profile, sc_pkcs15_card_t *p15card
/* PINs are even numbered, PUKs are odd */
if (!(preferred & 1))
preferred++;
if (preferred >= 126)
return SC_ERROR_TOO_MANY_OBJECTS;
}
if (current > preferred || preferred > INCRYPTO34_PIN_ID_MAX)

View File

@ -1719,6 +1719,7 @@ sc_pkcs15init_store_data_object(struct sc_pkcs15_card *p15card,
strlcpy(data_object_info->app_label, label, sizeof(data_object_info->app_label));
data_object_info->app_oid = args->app_oid;
sc_der_copy(&data_object_info->data, &args->der_encoded);
r = sc_pkcs15init_store_data(p15card, profile, object, &args->der_encoded, &data_object_info->path);
LOG_TEST_RET(ctx, r, "Store 'DATA' object error");

View File

@ -401,11 +401,12 @@ static int sc_hsm_decode_gakp_ec(struct sc_pkcs15_card *p15card,
pubkey->alg_id->algorithm = SC_ALGORITHM_EC;
pubkey->alg_id->params = ecp;
sc_copy_asn1_entry(c_asn1_ec_pointQ, asn1_ec_pointQ);
sc_format_asn1_entry(asn1_ec_pointQ + 0, cvc->publicPoint, &cvc->publicPointlen, 1);
r = sc_asn1_encode(p15card->card->ctx, asn1_ec_pointQ, &pubkey->u.ec.ecpointQ.value, &pubkey->u.ec.ecpointQ.len);
LOG_TEST_RET(p15card->card->ctx, r, "ASN.1 encoding failed");
pubkey->u.ec.ecpointQ.value = malloc(cvc->publicPointlen);
if (!pubkey->u.ec.ecpointQ.value) {
LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_OUT_OF_MEMORY);
}
memcpy(pubkey->u.ec.ecpointQ.value, cvc->publicPoint, cvc->publicPointlen);
pubkey->u.ec.ecpointQ.len = cvc->publicPointlen;
LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
}
@ -698,7 +699,7 @@ static int sc_hsm_emu_update_dcod(struct sc_profile *profile, struct sc_pkcs15_c
r = sc_pkcs15_encode_dodf_entry(p15card->card->ctx, object, &buf, &buflen);
LOG_TEST_RET(p15card->card->ctx, r, "Error encoding DCOD entry");
r = sc_hsm_update_ef(p15card, DCOD_PREFIX, data_info->path.value[1], 0, buf, buflen);
r = sc_hsm_update_ef(p15card, DCOD_PREFIX, data_info->path.value[data_info->path.len - 1], 0, buf, buflen);
free(buf);
return r;
}
@ -723,7 +724,7 @@ static int sc_hsm_emu_update_cd(struct sc_profile *profile, struct sc_pkcs15_car
r = sc_pkcs15_encode_cdf_entry(p15card->card->ctx, object, &buf, &buflen);
LOG_TEST_RET(p15card->card->ctx, r, "Error encoding CD entry");
r = sc_hsm_update_ef(p15card, CD_PREFIX, cert_info->path.value[1], 0, buf, buflen);
r = sc_hsm_update_ef(p15card, CD_PREFIX, cert_info->path.value[cert_info->path.len - 1], 0, buf, buflen);
free(buf);
return r;
}
@ -745,7 +746,7 @@ static int sc_hsm_emu_delete_cd(struct sc_profile *profile, struct sc_pkcs15_car
return SC_SUCCESS;
}
return sc_hsm_delete_ef(p15card, CD_PREFIX, ((struct sc_pkcs15_data_info *)object->data)->path.value[1]);
return sc_hsm_delete_ef(p15card, CD_PREFIX, cert_info->path.value[cert_info->path.len - 1]);
}

View File

@ -110,7 +110,7 @@ static struct map fileOpNames[] = {
{ "SELECT", SC_AC_OP_SELECT },
{ "LOCK", SC_AC_OP_LOCK },
{ "DELETE", SC_AC_OP_DELETE },
{ "DELETE_SELF",SC_AC_OP_DELETE_SELF },
{ "DELETE-SELF",SC_AC_OP_DELETE_SELF },
{ "CREATE", SC_AC_OP_CREATE },
{ "REHABILITATE",SC_AC_OP_REHABILITATE },
{ "INVALIDATE", SC_AC_OP_INVALIDATE },
@ -128,6 +128,7 @@ static struct map fileOpNames[] = {
{ "INTERNAL-AUTHENTICATE", SC_AC_OP_INTERNAL_AUTHENTICATE },
{ "PSO-DECRYPT", SC_AC_OP_PSO_DECRYPT },
{ "RESIZE", SC_AC_OP_RESIZE },
{ "ADMIN", SC_AC_OP_ADMIN },
{ NULL, 0 }
};
static struct map fileTypeNames[] = {

View File

@ -6,11 +6,14 @@ EXTRA_DIST = Makefile.mak
AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(OPTIONAL_READLINE_CFLAGS)
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/common -I$(top_builddir)/src/include
LIBS = $(top_builddir)/src/libopensc/libopensc.la $(top_builddir)/src/common/libcompat.la
LIBS = $(top_builddir)/src/libsm/libsm.la \
$(top_builddir)/src/libopensc/libopensc.la \
$(top_builddir)/src/common/libcompat.la
lib_LTLIBRARIES = libsmm-local.la
libsmm_local_la_SOURCES = smm-local.c sm-module.h sm-common.c sm-global-platform.c sm-cwa14890.c \
libsmm_local_la_SOURCES = smm-local.c sm-module.h \
sm-global-platform.c sm-cwa14890.c \
sm-card-authentic.c sm-card-iasecc.c \
smm-local.exports
libsmm_local_la_LIBADD = $(OPTIONAL_OPENSSL_LIBS) ../libopensc/libopensc.la

View File

@ -2,17 +2,17 @@ TOPDIR = ..\..
TARGET = smm-local.dll
OBJECTS = smm-local.obj sm-common.obj sm-global-platform.obj sm-cwa14890.obj sm-card-iasecc.obj sm-card-authentic.obj
OBJECTS = smm-local.obj sm-global-platform.obj sm-cwa14890.obj sm-card-iasecc.obj sm-card-authentic.obj
all: $(TARGET)
!INCLUDE $(TOPDIR)\win32\Make.rules.mak
$(TARGET): $(OBJECTS) ..\libopensc\opensc.lib
$(TARGET): $(OBJECTS) ..\libsm\libsm.lib ..\libopensc\opensc.lib
echo LIBRARY $* > $*.def
echo EXPORTS >> $*.def
type $*.exports >> $*.def
link /dll $(LINKFLAGS) /def:$*.def /out:$(TARGET) $(OBJECTS) ..\libopensc\opensc_a.lib $(ZLIB_LIB) $(OPENSSL_LIB) ..\common\libscdl.lib ws2_32.lib gdi32.lib advapi32.lib Crypt32.lib User32.lib
link /dll $(LINKFLAGS) /def:$*.def /out:$(TARGET) $(OBJECTS) ..\libsm\libsm.lib ..\libopensc\opensc_a.lib $(ZLIB_LIB) $(OPENSSL_LIB) ..\common\libscdl.lib ws2_32.lib gdi32.lib advapi32.lib Crypt32.lib User32.lib
if EXIST $(TARGET).manifest mt -manifest $(TARGET).manifest -outputresource:$(TARGET);2
.c.obj:

View File

@ -229,22 +229,6 @@ sm_cwa_init_session_keys(struct sc_context *ctx, struct sm_cwa_session *session_
}
void
sm_cwa_incr_ssc(struct sm_cwa_session *session_data)
{
int ii;
if (!session_data)
return;
for (ii=7; ii>=0; ii--) {
session_data->ssc[ii] += 1;
if (session_data->ssc[ii])
break;
}
}
int
sm_cwa_initialize(struct sc_context *ctx, struct sm_info *sm_info, struct sc_remote_data *rdata)
{
@ -335,7 +319,7 @@ sm_cwa_securize_apdu(struct sc_context *ctx, struct sm_info *sm_info, struct sc_
sc_log(ctx, "securize APDU (cla:%X,ins:%X,p1:%X,p2:%X,data(%i):%p)",
apdu->cla, apdu->ins, apdu->p1, apdu->p2, apdu->datalen, apdu->data);
sm_cwa_incr_ssc(session_data);
sm_incr_ssc(session_data->ssc, sizeof(session_data->ssc));
rv = sm_encrypt_des_cbc3(ctx, session_data->session_enc, apdu->data, apdu->datalen, &encrypted, &encrypted_len, 0);
LOG_TEST_RET(ctx, rv, "securize APDU: DES CBC3 encryption failed");
@ -419,7 +403,7 @@ sm_cwa_securize_apdu(struct sc_context *ctx, struct sm_info *sm_info, struct sc_
apdu->datalen = offs;
memcpy((unsigned char *)apdu->data, sbuf, offs);
sm_cwa_incr_ssc(session_data);
sm_incr_ssc(session_data->ssc, sizeof(session_data->ssc));
LOG_FUNC_RETURN(ctx, SC_SUCCESS);
}

View File

@ -248,7 +248,7 @@ sm_gp_get_mac(unsigned char *key, DES_cblock *icv,
block = malloc(in_len + 8);
if (!block)
return SC_ERROR_MEMORY_FAILURE;
return SC_ERROR_OUT_OF_MEMORY;
memcpy(block, in, in_len);
memcpy(block + in_len, "\x80\0\0\0\0\0\0\0", 8);

View File

@ -31,20 +31,7 @@ extern "C" {
#include <openssl/sha.h>
#include "libopensc/sm.h"
DES_LONG DES_cbc_cksum_3des(const unsigned char *in, DES_cblock *output, long length,
DES_key_schedule *schedule, DES_key_schedule *schedule2, const_DES_cblock *ivec);
DES_LONG DES_cbc_cksum_3des_emv96(const unsigned char *in, DES_cblock *output,
long length, DES_key_schedule *schedule, DES_key_schedule *schedule2,
const_DES_cblock *ivec);
int sm_encrypt_des_ecb3(unsigned char *key, unsigned char *data, int data_len,
unsigned char **out, int *out_len);
int sm_encrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
const unsigned char *in, size_t in_len,
unsigned char **out, size_t *out_len, int
not_force_pad);
int sm_decrypt_des_cbc3(struct sc_context *ctx, unsigned char *key,
unsigned char *data, size_t data_len, unsigned char **out, size_t *out_len);
#include "libsm/sm-common.h"
/* Global Platform definitions */
int sm_gp_get_mac(unsigned char *key, DES_cblock *icv, unsigned char *in, int in_len,

View File

@ -3,7 +3,7 @@ TOPDIR = ..\..
!INCLUDE $(TOPDIR)\win32\Make.rules.mak
TARGETS = opensc-tool.exe opensc-explorer.exe pkcs15-tool.exe pkcs15-crypt.exe \
pkcs11-tool.exe cardos-tool.exe eidenv.exe sc-hsm-tool.exe \
pkcs11-tool.exe cardos-tool.exe eidenv.exe sc-hsm-tool.exe openpgp-tool.exe \
$(PROGRAMS_OPENSSL)
$(TARGETS): $(TOPDIR)\win32\versioninfo.res util.obj

View File

@ -1,7 +1,7 @@
/*
* eidenv.c: EstEID utility
*
* Copyright (C) 2004 Martin Paljak <martin@paljak.pri.ee>
* Copyright (C) 2004 Martin Paljak <martin@martinpaljak.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public

View File

@ -104,6 +104,7 @@ static int do_random(int argc, char **argv);
static int do_get_data(int argc, char **argv);
static int do_put_data(int argc, char **argv);
static int do_apdu(int argc, char **argv);
static int do_sm(int argc, char **argv);
static int do_asn1(int argc, char **argv);
static int do_help(int argc, char **argv);
static int do_quit(int argc, char **argv);
@ -186,6 +187,9 @@ static struct command cmds[] = {
{ do_asn1,
"asn1", "[<file id>]",
"decode an ASN.1 file" },
{ do_sm,
"sm", "open|close",
"call SM 'open' or 'close' handlers, if available"},
{ do_debug,
"debug", "[<value>]",
"get/set the debug level" },
@ -1639,6 +1643,40 @@ err:
return -err;
}
static int do_sm(int argc, char **argv)
{
int r = SC_ERROR_NOT_SUPPORTED, ret = -1;
if (argc != 1)
return usage(do_sm);
#ifdef ENABLE_SM
if (!strcmp(argv[0],"open")) {
if (!card->sm_ctx.ops.open) {
printf("Not supported\n");
return -1;
}
r = card->sm_ctx.ops.open(card);
}
else if (!strcmp(argv[0],"close")) {
if (!card->sm_ctx.ops.close) {
printf("Not supported\n");
return -1;
}
r = card->sm_ctx.ops.close(card);
}
#endif
if (r == SC_SUCCESS) {
ret = 0;
printf("Success!\n");
}
else {
printf("Failure: %s\n", sc_strerror(r));
}
return ret;
}
static int do_help(int argc, char **argv)
{
struct command *cmd;

View File

@ -86,7 +86,7 @@ static const char *option_help[] = {
"authenticate using default 3des key",
"Generate key <ref>:<alg> 9A:06 on card, and output pubkey",
"Load an object <containerID> containerID as defined in 800-73 without leading 0x",
"Load a cert <ref> where <ref> is 9A,9B,9C or 9D",
"Load a cert <ref> where <ref> is 9A,9C,9D or 9E",
"Load a cert that has been gziped <ref>",
"Output file for cert or key",
"Inout file for cert",
@ -268,13 +268,13 @@ static int gen_key(const char * key_info)
}
switch (buf[0]) {
case 0x9a:
case 0x9b:
case 0x9c:
case 0x9d:
case 0x9e:
keydata.key_num = buf[0];
break;
default:
fprintf(stderr, "<keyref>:<algid> must be 9A, 9B, 9C or 9D\n");
fprintf(stderr, "<keyref>:<algid> must be 9A, 9C, 9D or 9E\n");
return 2;
}

View File

@ -655,7 +655,9 @@ int main(int argc, char * argv[])
util_fatal("Failed to load pkcs11 module");
rv = p11->C_Initialize(NULL);
if (rv != CKR_OK)
if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED)
printf("\n*** Cryptoki library has already been initialized ***\n");
else if (rv != CKR_OK)
p11_fatal("C_Initialize", rv);
if (do_show_info)
@ -1783,6 +1785,7 @@ static int write_object(CK_SESSION_HANDLE session)
struct rsakey_info rsa;
struct gostkey_info gost;
EVP_PKEY *evp_key = NULL;
CK_KEY_TYPE type = CKK_RSA;
memset(&cert, 0, sizeof(cert));
memset(&rsa, 0, sizeof(rsa));
@ -1918,7 +1921,6 @@ static int write_object(CK_SESSION_HANDLE session)
n_privkey_attr++;
}
if (evp_key->type == EVP_PKEY_RSA) {
CK_KEY_TYPE type = CKK_RSA;
FILL_ATTR(privkey_templ[n_privkey_attr], CKA_KEY_TYPE, &type, sizeof(type));
n_privkey_attr++;
FILL_ATTR(privkey_templ[n_privkey_attr], CKA_MODULUS, rsa.modulus, rsa.modulus_len);
@ -4273,7 +4275,9 @@ static void test_kpgen_certwrite(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
util_fatal("Failed to load pkcs11 module");
rv = p11->C_Initialize(NULL);
if (rv != CKR_OK)
if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED)
printf("\n*** Cryptoki library has already been initialized ***\n");
else if (rv != CKR_OK)
p11_fatal("C_Initialize", rv);
rv = p11->C_OpenSession(opt_slot, CKF_SERIAL_SESSION| CKF_RW_SESSION,

View File

@ -292,6 +292,7 @@ static const char *action_names[] = {
"verify that card is pristine",
"erase card",
"create PKCS #15 meta structure",
"delete object(s)",
"store PIN",
"generate key",
"store private key",
@ -300,9 +301,10 @@ static const char *action_names[] = {
"update certificate",
"store data object",
"finalizing card",
"delete object(s)",
"change attribute(s)",
"check card's sanity",
"update 'last-update'",
"erase application"
};
#define MAX_CERTS 4
@ -1200,6 +1202,10 @@ do_store_data_object(struct sc_profile *profile)
args.app_label = opt_application_name ? opt_application_name : "pkcs15-init";
sc_format_oid(&args.app_oid, opt_application_id);
if (opt_application_id && (args.app_oid.value[0] == -1)) {
util_error("Invalid OID \"%s\"", opt_application_id);
return SC_ERROR_INVALID_ARGUMENTS;
}
r = do_read_data_object(opt_infile, &data, &datalen);
if (r >= 0) {

View File

@ -45,7 +45,7 @@ static const char *app_name = "pkcs15-tool";
static int opt_wait = 0;
static int opt_no_cache = 0;
static char * opt_auth_id;
static char * opt_auth_id = NULL;
static char * opt_reader = NULL;
static char * opt_cert = NULL;
static char * opt_data = NULL;

View File

@ -35,7 +35,8 @@
#include <openssl/opensslconf.h>
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
#include "libopensc/opensc.h"
#include "libopensc/cardctl.h"
@ -56,32 +57,36 @@ static int verbose = 0;
// Some reasonable maximums
#define MAX_CERT 4096
#define MAX_PRKD 256
#define MAX_KEY 512
#define MAX_KEY 1024
#define MAX_WRAPPED_KEY (MAX_CERT + MAX_PRKD + MAX_KEY)
enum {
OPT_SO_PIN = 0x100,
OPT_PIN,
OPT_RETRY,
OPT_PASSWORD
OPT_PASSWORD,
OPT_PASSWORD_SHARES_THRESHOLD,
OPT_PASSWORD_SHARES_TOTAL
};
static const struct option options[] = {
{ "initialize", 0, NULL, 'X' },
{ "create-dkek-share", 1, NULL, 'C' },
{ "import-dkek-share", 1, NULL, 'I' },
{ "wrap-key", 1, NULL, 'W' },
{ "unwrap-key", 1, NULL, 'U' },
{ "dkek-shares", 1, NULL, 's' },
{ "so-pin", 1, NULL, OPT_SO_PIN },
{ "pin", 1, NULL, OPT_PIN },
{ "pin-retry", 1, NULL, OPT_RETRY },
{ "password", 1, NULL, OPT_PASSWORD },
{ "key-reference", 1, NULL, 'i' },
{ "force", 0, NULL, 'f' },
{ "reader", 1, NULL, 'r' },
{ "wait", 0, NULL, 'w' },
{ "verbose", 0, NULL, 'v' },
{ "initialize", 0, NULL, 'X' },
{ "create-dkek-share", 1, NULL, 'C' },
{ "import-dkek-share", 1, NULL, 'I' },
{ "wrap-key", 1, NULL, 'W' },
{ "unwrap-key", 1, NULL, 'U' },
{ "dkek-shares", 1, NULL, 's' },
{ "so-pin", 1, NULL, OPT_SO_PIN },
{ "pin", 1, NULL, OPT_PIN },
{ "pin-retry", 1, NULL, OPT_RETRY },
{ "password", 1, NULL, OPT_PASSWORD },
{ "pwd-shares-threshold", 1, NULL, OPT_PASSWORD_SHARES_THRESHOLD },
{ "pwd-shares-total", 1, NULL, OPT_PASSWORD_SHARES_TOTAL },
{ "key-reference", 1, NULL, 'i' },
{ "force", 0, NULL, 'f' },
{ "reader", 1, NULL, 'r' },
{ "wait", 0, NULL, 'w' },
{ "verbose", 0, NULL, 'v' },
{ NULL, 0, NULL, 0 }
};
@ -96,6 +101,8 @@ static const char *option_help[] = {
"Define user PIN",
"Define user PIN retry counter",
"Define password for DKEK share",
"Define threshold for number of password shares required for reconstruction",
"Define number of password shares",
"Key reference for key wrap/unwrap",
"Force replacement of key and certificate",
"Uses reader number <arg> [0]",
@ -103,6 +110,10 @@ static const char *option_help[] = {
"Verbose operation. Use several times to enable debug output.",
};
typedef struct {
BIGNUM x;
BIGNUM y;
} secret_share_t;
static sc_context_t *ctx = NULL;
static sc_card_t *card = NULL;
@ -110,7 +121,316 @@ static sc_card_t *card = NULL;
static void print_dkek_info(sc_cardctl_sc_hsm_dkek_t *dkekinfo) {
/**
* Generate a prime number
*
* The internal CPRNG is seeded using the provided seed value.
* For the bit size of the generated prime the following condition holds:
*
* num_bits(prime) > max(2^r, num_bits(n + 1))
*
* r equals the number of bits needed to encode the secret.
*
* @param prime Pointer for storage of prime number
* @param s Secret to share
* @param n Maximum number of shares
* @param rngSeed Seed value for CPRNG
*
*/
static void generatePrime(BIGNUM *prime, const BIGNUM *s, const unsigned int n, char *rngSeed)
{
int bits = 0;
// Seed the RNG
RAND_seed(rngSeed, sizeof(rngSeed));
// Determine minimum number of bits for prime >= max(2^r, n + 1)
bits = BN_num_bits_word(n + 1) > BN_num_bits(s) ? (BN_num_bits_word(n + 1)) : (BN_num_bits(s));
// Clear the prime value
BN_clear(prime);
// Generate random prime
BN_generate_prime(prime, bits, 1, NULL, NULL, NULL, NULL );
}
/**
* Helper method to calculate the y-value
* for a given x-value and a polynomial
*
* @param x X-value
* @param polynomial The underlying polynomial
* @param t Threshold (determines the degree of the polynomial)
* @param prime Prime for finite field arithmetic
* @param y Pointer for storage of calculated y-value
*/
static void calculatePolynomialValue(const BIGNUM x, BIGNUM **polynomial, const unsigned char t, const BIGNUM prime, BIGNUM *y)
{
BIGNUM **pp;
BIGNUM temp;
BIGNUM exponent;
unsigned long exp;
BN_CTX *ctx;
// Create context for temporary variables of OpenSSL engine
ctx = BN_CTX_new();
BN_CTX_init(ctx);
BN_init(&temp);
BN_init(&exponent);
// Set y to ZERO
BN_zero(y);
/* Initialize the result using the secret value at position 0 of the polynomial */
pp = polynomial;
BN_copy(y, *pp);
pp++;
for (exp = 1; exp < t; exp++) {
BN_copy(&temp, &x);
BN_set_word(&exponent, exp);
// temp = x^exponent mod prime
BN_mod_exp(&temp, &x, &exponent, &prime, ctx);
// exponent = temp * a = a * x^exponent mod prime
BN_mod_mul(&exponent, &temp, *pp, &prime, ctx);
// add the temp value from exponent to y
BN_copy(&temp, y);
BN_mod_add(y, &temp, &exponent, &prime, ctx);
pp++;
}
BN_clear_free(&temp);
BN_clear_free(&exponent);
BN_CTX_free(ctx);
}
/**
* Create shares depending on the provided parameters
*
* @param s Secret value to share
* @param t Threshold needed to reconstruct the secret
* @param n Total number of shares
* @param prime Prime for finite field arithmetic
* @param shares Pointer for storage of calculated shares (must be big enough to hold n shares)
*/
static int createShares(const BIGNUM *s, const unsigned char t, const unsigned char n, const BIGNUM prime, secret_share_t *shares)
{
// Array representing the polynomial a(x) = s + a_1 * x + ... + a_n-1 * x^n-1 mod p
BIGNUM **polynomial = malloc(n * sizeof(BIGNUM *));
BIGNUM **pp;
unsigned long i;
secret_share_t *sp;
// Set the secret value as the constant part of the polynomial
pp = polynomial;
*pp = BN_new();
BN_init(*pp);
BN_copy(*pp, s);
pp++;
// Initialize and generate some random values for coefficients a_x in the remaining polynomial
for (i = 1; i < t; i++) {
*pp = BN_new();
BN_init(*pp);
BN_rand_range(*pp, &prime);
pp++;
}
sp = shares;
// Now calculate n secret shares
for (i = 1; i <= n; i++) {
BN_init(&(sp->x));
BN_init(&(sp->y));
BN_set_word(&(sp->x), i);
calculatePolynomialValue(sp->x, polynomial, t, prime, &(sp->y));
sp++;
}
// Deallocate the resource of the polynomial
pp = polynomial;
for (i = 0; i < t; i++) {
BN_clear_free(*pp);
pp++;
}
free(polynomial);
return 0;
}
/**
* Reconstruct secret using the provided shares
*
* @param shares Shares used to reconstruct secret (should contain t entries)
* @param t Threshold used to reconstruct the secret
* @param prime Prime for finite field arithmetic
* @param s Pointer for storage of calculated secred
*/
static int reconstructSecret(secret_share_t *shares, unsigned char t, const BIGNUM prime, BIGNUM *s)
{
unsigned char i;
unsigned char j;
// Array representing the polynomial a(x) = s + a_1 * x + ... + a_n-1 * x^n-1 mod p
BIGNUM **bValue = malloc(t * sizeof(BIGNUM *));
BIGNUM **pbValue;
BIGNUM numerator;
BIGNUM denominator;
BIGNUM temp;
secret_share_t *sp_i;
secret_share_t *sp_j;
BN_CTX *ctx;
// Initialize
pbValue = bValue;
for (i = 0; i < t; i++) {
*pbValue = BN_new();
BN_init(*pbValue);
pbValue++;
}
BN_init(&numerator);
BN_init(&denominator);
BN_init(&temp);
// Create context for temporary variables of engine
ctx = BN_CTX_new();
BN_CTX_init(ctx);
pbValue = bValue;
sp_i = shares;
for (i = 0; i < t; i++) {
BN_one(&numerator);
BN_one(&denominator);
sp_j = shares;
for (j = 0; j < t; j++) {
if (i == j) {
sp_j++;
continue;
}
BN_mul(&numerator, &numerator, &(sp_j->x), ctx);
BN_sub(&temp, &(sp_j->x), &(sp_i->x));
BN_mul(&denominator, &denominator, &temp, ctx);
sp_j++;
}
/*
* Use the modular inverse value of the denominator for the
* multiplication
*/
if (BN_mod_inverse(&denominator, &denominator, &prime, ctx) == NULL ) {
return -1;
}
BN_mod_mul(*pbValue, &numerator, &denominator, &prime, ctx);
pbValue++;
sp_i++;
}
/*
* Calculate the secret by multiplying all y-values with their
* corresponding intermediate values
*/
pbValue = bValue;
sp_i = shares;
BN_zero(s);
for (i = 0; i < t; i++) {
BN_mul(&temp, &(sp_i->y), *pbValue, ctx);
BN_add(s, s, &temp);
pbValue++;
sp_i++;
}
// Perform modulo operation and copy result
BN_nnmod(&temp, s, &prime, ctx);
BN_copy(s, &temp);
BN_clear_free(&numerator);
BN_clear_free(&denominator);
BN_clear_free(&temp);
BN_CTX_free(ctx);
// Deallocate the resource of the polynomial
pbValue = bValue;
for (i = 0; i < t; i++) {
BN_clear_free(*pbValue);
pbValue++;
}
free(bValue);
return 0;
}
/**
* Helper method to free allocated resources
*
* @param shares Shares to be freed
* @param n Total number of shares to freed
*/
static int cleanUpShares(secret_share_t *shares, unsigned char n)
{
int i;
secret_share_t *sp;
sp = shares;
for (i = 0; i < n; i++) {
BN_clear_free(&(sp->x));
BN_clear_free(&(sp->y));
sp++;
}
free(shares);
return 0;
}
void clearScreen()
{
if (system( "clear" )) system( "cls" );
}
void waitForEnterKeyPressed()
{
char c;
fflush(stdout);
while ((c = getchar()) != '\n' && c != EOF) {
}
}
static void print_dkek_info(sc_cardctl_sc_hsm_dkek_t *dkekinfo)
{
printf("DKEK shares : %d\n", dkekinfo->dkek_shares);
if (dkekinfo->outstanding_shares > 0) {
printf("DKEK import pending, %d share(s) still missing\n",dkekinfo->outstanding_shares);
@ -248,14 +568,103 @@ static void initialize(sc_card_t *card, const char *so_pin, const char *user_pin
static void import_dkek_share(sc_card_t *card, const char *inf, int iter, char *password)
static int recreate_password_from_shares(char **pwd, int *pwdlen, int num_of_password_shares)
{
int r, i;
BIGNUM prime;
BIGNUM secret;
BIGNUM *p;
char inbuf[64];
char bin[64];
size_t binlen = 0;
char *ip;
secret_share_t *shares = NULL;
secret_share_t *sp;
/*
* Initialize prime and secret
*/
BN_init(&prime);
BN_init(&secret);
// Allocate data buffer for the shares
shares = malloc(num_of_password_shares * sizeof(secret_share_t));
printf("\nDeciphering the DKEK for import into the SmartCard-HSM requires %i key custodians", num_of_password_shares);
printf("\nto present their share. Only the first key custodian needs to enter the public prime.");
printf("\nPlease remember to present the share id as well as the share value.");
printf("\n\nPlease enter prime: ");
memset(inbuf, 0, sizeof(inbuf));
fgets(inbuf, sizeof(inbuf), stdin);
binlen = 64;
sc_hex_to_bin(inbuf, bin, &binlen);
BN_bin2bn(bin, binlen, &prime);
sp = shares;
for (i = 0; i < num_of_password_shares; i++) {
clearScreen();
printf("Press <enter> to enter share %i of %i\n\n", i + 1, num_of_password_shares);
waitForEnterKeyPressed();
clearScreen();
BN_init(&(sp->x));
BN_init(&(sp->y));
printf("Share %i of %i\n\n", i + 1, num_of_password_shares);
printf("Please enter share ID: ");
memset(inbuf, 0, sizeof(inbuf));
fgets(inbuf, sizeof(inbuf), stdin);
p = &(sp->x);
BN_hex2bn(&p, inbuf);
printf("Please enter share value: ");
memset(inbuf, 0, sizeof(inbuf));
fgets(inbuf, sizeof(inbuf), stdin);
binlen = 64;
sc_hex_to_bin(inbuf, bin, &binlen);
BN_bin2bn(bin, binlen, &(sp->y));
sp++;
}
clearScreen();
r = reconstructSecret(shares, num_of_password_shares, prime, &secret);
if (r < 0) {
printf("\nError during reconstruction of secret. Wrong shares?\n");
return r;
}
/*
* Encode the secret value
*/
ip = inbuf;
*pwdlen = BN_bn2bin(&secret, ip);
*pwd = calloc(1, *pwdlen);
memcpy(*pwd, ip, *pwdlen);
cleanUpShares(shares, num_of_password_shares);
BN_clear_free(&prime);
BN_clear_free(&secret);
return 0;
}
static void import_dkek_share(sc_card_t *card, const char *inf, int iter, char *password, int num_of_password_shares)
{
sc_cardctl_sc_hsm_dkek_t dkekinfo;
EVP_CIPHER_CTX ctx;
FILE *in = NULL;
u8 filebuff[64],key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH],outbuff[64];
char *pwd = NULL;
int r, outlen;
int r, outlen, pwdlen;
in = fopen(inf, "rb");
@ -277,15 +686,26 @@ static void import_dkek_share(sc_card_t *card, const char *inf, int iter, char *
}
if (password == NULL) {
printf("Enter password to decrypt DKEK share : ");
util_getpass(&pwd, NULL, stdin);
printf("\n");
if (num_of_password_shares == -1) {
printf("Enter password to decrypt DKEK share : ");
util_getpass(&pwd, NULL, stdin);
pwdlen = strlen(pwd);
printf("\n");
} else {
r = recreate_password_from_shares(&pwd, &pwdlen, num_of_password_shares);
if (r < 0) {
return;
}
}
} else {
pwd = password;
pwdlen = strlen(password);
}
printf("Deciphering DKEK share, please wait...\n");
EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), filebuff + 8, (u8 *)pwd, strlen(pwd), iter, key, iv);
EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), filebuff + 8, (u8 *)pwd, pwdlen, iter, key, iv);
OPENSSL_cleanse(pwd, strlen(pwd));
if (password == NULL) {
@ -316,6 +736,7 @@ static void import_dkek_share(sc_card_t *card, const char *inf, int iter, char *
EVP_CIPHER_CTX_cleanup(&ctx);
if (r == SC_ERROR_INS_NOT_SUPPORTED) { // Not supported or not initialized for key shares
printf("Not supported by card or card not initialized for key share usage\n");
return;
}
@ -329,46 +750,172 @@ static void import_dkek_share(sc_card_t *card, const char *inf, int iter, char *
static void create_dkek_share(sc_card_t *card, const char *outf, int iter, char *password)
static void ask_for_password(char **pwd, int *pwdlen)
{
char *refpwd = NULL;
printf( "\nThe DKEK share will be enciphered using a key derived from a user supplied password.\n");
printf( "The security of the DKEK share relies on a well chosen and sufficiently long password.\n");
printf( "The recommended length is more than 10 characters, which are mixed letters, numbers and\n");
printf("symbols.\n\n");
printf( "Please keep the generated DKEK share file in a safe location. We also recommend to keep a\n");
printf( "paper printout, in case the electronic version becomes unavailable. A printable version\n");
printf( "of the file can be generated using \"openssl base64 -in <filename>\".\n");
while (1) {
printf("Enter password to encrypt DKEK share : ");
util_getpass(pwd, NULL, stdin);
printf("\n");
if (strlen(*pwd) < 6) {
printf("Password way to short. Please retry.\n");
continue;
}
printf("Please retype password to confirm : ");
util_getpass(&refpwd, NULL, stdin);
printf("\n");
if (strcmp(*pwd, refpwd)) {
printf("Passwords do not match. Please retry.\n");
continue;
}
*pwdlen = strlen(*pwd);
break;
}
OPENSSL_cleanse(refpwd, strlen(refpwd));
free(refpwd);
}
static int generate_pwd_shares(sc_card_t *card, char **pwd, int *pwdlen, int password_shares_threshold, int password_shares_total)
{
int r, i;
BIGNUM prime;
BIGNUM secret;
char buf[64];
char hex[64];
int l;
secret_share_t *shares = NULL;
secret_share_t *sp;
u8 rngseed[16];
printf( "\nThe DKEK will be enciphered using a randomly generated 64 bit password.\n");
printf( "This password is split using a (%i-of-%i) threshold scheme.\n\n", password_shares_threshold, password_shares_total);
printf( "Please keep the generated and encrypted DKEK file in a safe location. We also recommend \n");
printf( "to keep a paper printout, in case the electronic version becomes unavailable. A printable version\n");
printf( "of the file can be generated using \"openssl base64 -in <filename>\".\n");
printf("\n\nPress <enter> to continue");
waitForEnterKeyPressed();
*pwd = calloc(1, 8);
*pwdlen = 8;
r = sc_get_challenge(card, *pwd, 8);
if (r < 0) {
printf("Error generating random key failed with ", sc_strerror(r));
OPENSSL_cleanse(pwd, *pwdlen);
free(pwd);
return r;
}
**pwd |= 0x80;
/*
* Initialize prime and secret
*/
BN_init(&prime);
BN_init(&secret);
/*
* Encode the secret value
*/
BN_bin2bn(*pwd, *pwdlen, &secret);
/*
* Generate seed and calculate a prime depending on the size of the secret
*/
r = sc_get_challenge(card, rngseed, 16);
if (r < 0) {
printf("Error generating random seed failed with ", sc_strerror(r));
OPENSSL_cleanse(pwd, *pwdlen);
free(pwd);
return r;
}
generatePrime(&prime, &secret, password_shares_total, rngseed);
// Allocate data buffer for the generated shares
shares = malloc(password_shares_total * sizeof(secret_share_t));
createShares(&secret, password_shares_threshold, password_shares_total, prime, shares);
sp = shares;
for (i = 0; i < password_shares_total; i++) {
clearScreen();
printf("Press <enter> to display key share %i of %i\n\n", i + 1, password_shares_total);
waitForEnterKeyPressed();
clearScreen();
printf("Share %i of %i\n\n", i + 1, password_shares_total);
l = BN_bn2bin(&prime, buf);
sc_bin_to_hex(buf, l, hex, 64, ':');
printf("\nPrime : %s\n", hex);
printf("Share ID : %s\n", BN_bn2dec(&(sp->x)));
l = BN_bn2bin(&(sp->y), buf);
sc_bin_to_hex(buf, l, hex, 64, ':');
printf("Share value : %s\n", hex);
printf("\n\nPlease note ALL values above and press <enter> when finished");
waitForEnterKeyPressed();
sp++;
}
clearScreen();
cleanUpShares(shares, password_shares_total);
BN_clear_free(&prime);
BN_clear_free(&secret);
return 0;
}
static void create_dkek_share(sc_card_t *card, const char *outf, int iter, char *password, int password_shares_threshold, int password_shares_total)
{
EVP_CIPHER_CTX ctx;
FILE *out = NULL;
u8 filebuff[64],key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH],outbuff[64];
u8 filebuff[64], key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
u8 dkek_share[32];
char *pwd = NULL;
int r, outlen;
int r = 0, outlen, pwdlen = 0;
if (password == NULL) {
char *refpwd = NULL;
printf("\nThe DKEK share will be enciphered using a key derived from a user supplied password.\n");
printf("The security of the DKEK share relies on a well chosen and sufficiently long password.\n");
printf("The recommended length is more than 10 characters, which are mixed letters, numbers and\n");
printf("symbols.\n\n");
printf("Please keep the generated DKEK share file in a save location. We also recommend to keep a\n");
printf("paper printout, in case the electronic version becomes unavailable. A printable version\n");
printf("of the file can be generated using \"openssl base64 -in <filename>\".\n");
while(1) {
printf("Enter password to encrypt DKEK share : ");
util_getpass(&pwd, NULL, stdin);
printf("\n");
if (strlen(pwd) < 6) {
printf("Password way to short. Please retry.\n");
continue;
}
printf("Please retype password to confirm : ");
util_getpass(&refpwd, NULL, stdin);
printf("\n");
if (strcmp(pwd, refpwd)) {
printf("Passwords do not match. Please retry.\n");
continue;
}
break;
if (password_shares_threshold == -1) {
ask_for_password(&pwd, &pwdlen);
} else { // create password using threshold scheme
r = generate_pwd_shares(card, &pwd, &pwdlen, password_shares_threshold, password_shares_total);
}
OPENSSL_cleanse(refpwd, strlen(refpwd));
free(refpwd);
} else {
pwd = password;
pwdlen = strlen(password);
}
if (r < 0) {
printf("Creating DKEK share failed");
return;
}
memcpy(filebuff, magic, sizeof(magic) - 1);
@ -380,10 +927,10 @@ static void create_dkek_share(sc_card_t *card, const char *outf, int iter, char
}
printf("Enciphering DKEK share, please wait...\n");
EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), filebuff + 8, (u8 *)pwd, strlen(pwd), iter, key, iv);
EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), filebuff + 8, (u8 *)pwd, pwdlen, iter, key, iv);
if (password == NULL) {
OPENSSL_cleanse(pwd, strlen(pwd));
OPENSSL_cleanse(pwd, pwdlen);
free(pwd);
}
@ -442,6 +989,50 @@ static size_t determineLength(const u8 *tlv, size_t buflen)
/**
* Encapsulate data object as TLV object
*
* @param tag the one byte tag
* @param indata the value field
* @param inlen the length of the value field
* @param outdata pointer to the allocated memory buffer
* @param outlen the size of the TLV object
*/
static int wrap_with_tag(u8 tag, u8 *indata, size_t inlen, u8 **outdata, size_t *outlen)
{
int nlc = 0;
u8 *ptr;
if (inlen > 127) {
do {
nlc++;
} while (inlen >= (1 << (nlc << 3)));
}
*outlen = 2 + nlc + inlen;
ptr = malloc(*outlen);
if (ptr == NULL) {
return SC_ERROR_OUT_OF_MEMORY;
}
*outdata = ptr;
*ptr++ = tag;
if (nlc) {
*ptr++ = 0x80 | nlc;
while (nlc--) {
*ptr++ = (inlen >> (nlc << 3)) & 0xFF;
}
} else {
*ptr++ = inlen & 0x7F;
}
memcpy(ptr, indata, inlen);
return SC_SUCCESS;
}
static void wrap_key(sc_card_t *card, u8 keyid, const char *outf, const char *pin)
{
sc_cardctl_sc_hsm_wrapped_key_t wrapped_key;
@ -452,6 +1043,7 @@ static void wrap_key(sc_card_t *card, u8 keyid, const char *outf, const char *pi
u8 fid[2];
u8 ef_prkd[MAX_PRKD];
u8 ef_cert[MAX_CERT];
u8 wrapped_key_buff[MAX_KEY];
u8 keyblob[MAX_WRAPPED_KEY];
u8 *key;
u8 *ptr;
@ -486,6 +1078,8 @@ static void wrap_key(sc_card_t *card, u8 keyid, const char *outf, const char *pi
}
wrapped_key.key_id = keyid;
wrapped_key.wrapped_key = wrapped_key_buff;
wrapped_key.wrapped_key_length = sizeof(wrapped_key_buff);
r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_WRAP_KEY, (void *)&wrapped_key);
@ -537,13 +1131,12 @@ static void wrap_key(sc_card_t *card, u8 keyid, const char *outf, const char *pi
}
}
ptr = keyblob;
// Encode key in octet string object
sc_asn1_write_element(card->ctx, SC_ASN1_OCTET_STRING,
wrapped_key.wrapped_key, wrapped_key.wrapped_key_length,
&key, &key_len);
key_len = 0;
wrap_with_tag(0x04, wrapped_key.wrapped_key, wrapped_key.wrapped_key_length,
&key, &key_len);
memcpy(ptr, key, key_len);
ptr += key_len;
@ -561,10 +1154,9 @@ static void wrap_key(sc_card_t *card, u8 keyid, const char *outf, const char *pi
ptr += ef_cert_len;
}
// Encode key in octet string object
sc_asn1_write_element(card->ctx, SC_ASN1_SEQUENCE|SC_ASN1_CONS,
keyblob, ptr - keyblob,
&key, &key_len);
// Encode key, key decription and certificate object in sequence
key_len = 0;
wrap_with_tag(0x30, keyblob, ptr - keyblob, &key, &key_len);
out = fopen(outf, "wb");
@ -589,7 +1181,6 @@ static void wrap_key(sc_card_t *card, u8 keyid, const char *outf, const char *pi
static int update_ef(sc_card_t *card, u8 prefix, u8 id, int erase, const u8 *buf, size_t buflen)
{
sc_file_t *file = NULL;
sc_file_t newfile;
sc_path_t path;
u8 fid[2];
int r;
@ -805,6 +1396,8 @@ int main(int argc, char * const argv[])
int opt_retry_counter = 3;
int opt_dkek_shares = -1;
int opt_key_reference = -1;
int opt_password_shares_threshold = -1;
int opt_password_shares_total = -1;
int opt_force = 0;
int opt_iter = 10000000;
sc_context_param_t ctx_param;
@ -855,6 +1448,12 @@ int main(int argc, char * const argv[])
case OPT_RETRY:
opt_retry_counter = atol(optarg);
break;
case OPT_PASSWORD_SHARES_THRESHOLD:
opt_password_shares_threshold = atol(optarg);
break;
case OPT_PASSWORD_SHARES_TOTAL:
opt_password_shares_total = atol(optarg);
break;
case 's':
opt_dkek_shares = atol(optarg);
break;
@ -896,22 +1495,29 @@ int main(int argc, char * const argv[])
}
err = util_connect_card(ctx, &card, opt_reader, opt_wait, verbose);
if (err)
if (r != SC_SUCCESS) {
fprintf(stderr, "Failed to connect to card: %s\n", sc_strerror(r));
goto end;
}
sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0);
r = sc_select_file(card, &path, &file);
if (r != SC_SUCCESS) {
fprintf(stderr, "Failed to select application: %s\n", sc_strerror(r));
goto end;
}
if (do_initialize) {
initialize(card, opt_so_pin, opt_pin, opt_retry_counter, opt_dkek_shares);
}
if (do_create_dkek_share) {
create_dkek_share(card, opt_filename, opt_iter, opt_password);
create_dkek_share(card, opt_filename, opt_iter, opt_password, opt_password_shares_threshold, opt_password_shares_total);
}
if (do_import_dkek_share) {
import_dkek_share(card, opt_filename, opt_iter, opt_password);
import_dkek_share(card, opt_filename, opt_iter, opt_password, opt_password_shares_total);
}
if (do_wrap_key) {

View File

@ -307,6 +307,21 @@ const char * util_acl_to_str(const sc_acl_entry_t *e)
if (e->key_ref != SC_AC_KEY_REF_NONE)
sprintf(buf + 4, "%d", e->key_ref);
break;
case SC_AC_SEN:
strcpy(buf, "Sec.Env. ");
if (e->key_ref != SC_AC_KEY_REF_NONE)
sprintf(buf + 3, "#%d", e->key_ref);
break;
case SC_AC_SCB:
strcpy(buf, "Sec.ControlByte ");
if (e->key_ref != SC_AC_KEY_REF_NONE)
sprintf(buf + 3, "Ox%X", e->key_ref);
break;
case SC_AC_IDA:
strcpy(buf, "PKCS#15 AuthID ");
if (e->key_ref != SC_AC_KEY_REF_NONE)
sprintf(buf + 3, "#%d", e->key_ref);
break;
default:
strcpy(buf, "????");
break;

View File

@ -1,79 +0,0 @@
Makefile
Makefile.in
core
archive
acinclude.m4
aclocal.m4
autom4te.cache
compile
confdefs.h
config.*
configure
conftest
conftest.c
depcomp
install-sh
libtool
libtool.m4
lt*.m4
ltmain.sh
missing
mkinstalldirs
so_locations
stamp-h*
.deps
.libs
.#*#
.*.bak
.*.orig
.*.rej
.*~
#*#
*.bak
*.d
*.def
*.dll
*.exe
*.la
*.lib
*.lo
*.orig
*.pdb
*.rej
*.u
*.rc
*.pc
*~
*.gz
*.bz2
*.[0-9]
*.html
*.gif
*.css
*.out
*.tmp
ChangeLog
opensc.conf
xsl-stylesheets
opensc-config
test-conf
pkcs15-tool
pkcs15-crypt
pkcs15-init
piv-tool
eidenv
opensc-explorer
opensc-tool
rutoken-tool
cardos-info
cryptoflex-tool
netkey-tool
pkcs11-tool
pintest
p15dump
prngtest
base64
lottery

View File

@ -83,7 +83,7 @@
<File Source="$(var.SOURCE_DIR)\src\libopensc\opensc.dll" Vital="yes"/>
</Component>
<Component Id="smm_local.dll" Guid="*" Win64="$(var.Win64YesNo)">
<File Source="$(var.SOURCE_DIR)\src\sm\smm-local.dll" Vital="yes"/>
<File Source="$(var.SOURCE_DIR)\src\smm\smm-local.dll" Vital="yes"/>
</Component>
<Component Id="opensc_explorer.exe" Guid="*" Win64="$(var.Win64YesNo)">
<File Source="$(var.SOURCE_DIR)\src\tools\opensc-explorer.exe" Vital="yes"/>
@ -106,6 +106,9 @@
<Component Id="sc_hsm_tool.exe" Guid="*" Win64="$(var.Win64YesNo)">
<File Source="$(var.SOURCE_DIR)\src\tools\sc-hsm-tool.exe" Vital="yes"/>
</Component>
<Component Id="openpgp_tool.exe" Guid="*" Win64="$(var.Win64YesNo)">
<File Source="$(var.SOURCE_DIR)\src\tools\openpgp-tool.exe" Vital="yes"/>
</Component>
</Directory>
<Directory Id="INSTALLDIR_PROFILES" Name="profiles">
<Component Id="pkcs15.profile" Guid="*" Win64="$(var.Win64YesNo)">
@ -215,6 +218,7 @@
<ComponentRef Id="pkcs15_tool.exe"/>
<ComponentRef Id="pkcs15_crypt.exe"/>
<ComponentRef Id="sc_hsm_tool.exe"/>
<ComponentRef Id="openpgp_tool.exe"/>
<!-- TODO: Not all profiles are listed! -->
<ComponentRef Id="pkcs15.profile"/>
<ComponentRef Id="asepcos.profile"/>