Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Tobias Hunger
qt-creator
Commits
993771f0
Commit
993771f0
authored
Dec 13, 2010
by
Pawel Polanski
Browse files
Capabilities and IMEIs can now be extracted form Dev Certs for SymbianOS
Reviewed-by: Alessandro Portale
parent
df43d55e
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/plugins/qt4projectmanager/qt-s60/certificatepathchooser.cpp
View file @
993771f0
...
...
@@ -40,7 +40,16 @@ CertificatePathChooser::CertificatePathChooser(QWidget *parent) :
bool
CertificatePathChooser
::
validatePath
(
const
QString
&
path
,
QString
*
errorMessage
)
{
if
(
Utils
::
PathChooser
::
validatePath
(
path
,
errorMessage
))
return
S60CertificateInfo
::
validateCertificate
(
path
,
errorMessage
)
==
S60CertificateInfo
::
CertificateValid
;
if
(
Utils
::
PathChooser
::
validatePath
(
path
,
errorMessage
))
{
QScopedPointer
<
S60CertificateInfo
>
certInfoPtr
(
new
S60CertificateInfo
(
path
));
if
(
certInfoPtr
.
data
()
->
validateCertificate
()
==
S60CertificateInfo
::
CertificateValid
)
{
if
(
errorMessage
)
*
errorMessage
=
certInfoPtr
.
data
()
->
toHtml
();
return
true
;
}
else
{
if
(
errorMessage
)
*
errorMessage
=
certInfoPtr
.
data
()
->
errorString
();
}
}
return
false
;
}
src/plugins/qt4projectmanager/qt-s60/s60certificateinfo.cpp
View file @
993771f0
...
...
@@ -32,42 +32,161 @@
#include
<QDateTime>
#include
<QFileInfo>
#include
<QCoreApplication>
#include
<QTextStream>
#include
"s60symbiancertificate.h"
S60CertificateInfo
::
CertificateState
S60CertificateInfo
::
validateCertificate
(
const
QString
&
certFilePath
,
QString
*
errorString
)
namespace
{
const
char
*
const
SIMPLE_DATE_FORMAT
=
"dd.MM.yyyy"
;
}
struct
Capability
{
const
char
*
name
;
const
int
value
;
};
static
const
Capability
capability
[]
=
{
{
"LocalServices"
,
S60CertificateInfo
::
LocalServices
},
{
"Location"
,
S60CertificateInfo
::
Location
},
{
"NetworkServices"
,
S60CertificateInfo
::
NetworkServices
},
{
"ReadUserData"
,
S60CertificateInfo
::
ReadUserData
},
{
"UserEnvironment"
,
S60CertificateInfo
::
UserEnvironment
},
{
"WriteUserData"
,
S60CertificateInfo
::
WriteUserData
},
{
"PowerMgmt"
,
S60CertificateInfo
::
PowerMgmt
},
{
"ProtServ"
,
S60CertificateInfo
::
ProtServ
},
{
"ReadDeviceData"
,
S60CertificateInfo
::
ReadDeviceData
},
{
"SurroundingsDD"
,
S60CertificateInfo
::
SurroundingsDD
},
{
"SwEvent"
,
S60CertificateInfo
::
SwEvent
},
{
"TrustedUI"
,
S60CertificateInfo
::
TrustedUI
},
{
"WriteDeviceData"
,
S60CertificateInfo
::
WriteDeviceData
},
{
"CommDD"
,
S60CertificateInfo
::
CommDD
},
{
"DiskAdmin"
,
S60CertificateInfo
::
DiskAdmin
},
{
"NetworkControl"
,
S60CertificateInfo
::
NetworkControl
},
{
"MultimediaDD"
,
S60CertificateInfo
::
MultimediaDD
},
{
"AllFiles"
,
S60CertificateInfo
::
AllFiles
},
{
"DRM"
,
S60CertificateInfo
::
DRM
},
{
"TCB"
,
S60CertificateInfo
::
TCB
}
};
QStringList
createCapabilityList
(
uint
capabilities
)
{
const
int
capabilityCount
=
sizeof
(
capability
)
/
sizeof
(
capability
[
0
]);
QStringList
capabilityList
;
for
(
int
i
=
0
;
i
<
capabilityCount
;
++
i
)
if
(
capabilities
&
capability
[
i
].
value
)
capabilityList
<<
QLatin1String
(
capability
[
i
].
name
);
return
capabilityList
;
}
S60CertificateInfo
::
S60CertificateInfo
(
const
QString
&
filePath
,
QObject
*
parent
)
:
QObject
(
parent
),
m_certificate
(
new
S60SymbianCertificate
(
filePath
)),
m_filePath
(
filePath
)
{
}
S60CertificateInfo
::~
S60CertificateInfo
()
{
delete
m_certificate
;
}
S60CertificateInfo
::
CertificateState
S60CertificateInfo
::
validateCertificate
()
{
CertificateState
result
=
CertificateValid
;
S60SymbianCertificate
*
certificate
=
new
S60SymbianCertificate
(
certFilePath
);
if
(
certificate
->
isValid
())
{
if
(
m_certificate
->
isValid
())
{
QDateTime
currentTime
(
QDateTime
::
currentDateTimeUtc
());
QDateTime
endTime
(
certificate
->
endTime
());
QDateTime
startTime
(
certificate
->
startTime
());
QDateTime
endTime
(
m_
certificate
->
endTime
());
QDateTime
startTime
(
m_
certificate
->
startTime
());
if
(
currentTime
>
endTime
)
{
if
(
errorString
)
*
errorString
=
QCoreApplication
::
translate
(
"S60Utils::validateCertificate"
,
"The
\"
%1
\"
certificate has already expired and cannot be used.
\n
Expiration date: %2."
)
.
arg
(
QFileInfo
(
certFilePath
).
fileName
())
.
arg
(
endTime
.
toLocalTime
().
toString
());
m_errorString
=
tr
(
"The
\"
%1
\"
certificate has already expired and cannot be used."
"
\n
Expiration date: %2."
)
.
arg
(
QFileInfo
(
m_filePath
).
fileName
())
.
arg
(
endTime
.
toLocalTime
().
toString
(
QLatin1String
(
SIMPLE_DATE_FORMAT
)));
result
=
CertificateError
;
}
else
if
(
currentTime
<
startTime
)
{
if
(
errorString
)
*
errorString
=
QCoreApplication
::
translate
(
"S60Utils::validateCertificate"
,
"The
\"
%1
\"
certificate is not yet valid.
\n
Valid from: %2."
)
.
arg
(
QFileInfo
(
certFilePath
).
fileName
())
.
arg
(
startTime
.
toLocalTime
().
toString
());
m_errorString
=
tr
(
"The
\"
%1
\"
certificate is not yet valid.
\n
Valid from: %2."
)
.
arg
(
QFileInfo
(
m_filePath
).
fileName
())
.
arg
(
startTime
.
toLocalTime
().
toString
(
QLatin1String
(
SIMPLE_DATE_FORMAT
)));
result
=
CertificateWarning
;
//This certificate may be valid in the near future
}
}
else
{
if
(
errorString
)
*
errorString
=
QCoreApplication
::
translate
(
"S60Utils::validateCertificate"
,
"The
\"
%1
\"
certificate is not a valid X.509 certificate."
)
.
arg
(
QFileInfo
(
certFilePath
).
baseName
());
m_errorString
=
tr
(
"The
\"
%1
\"
certificate is not a valid X.509 certificate."
)
.
arg
(
QFileInfo
(
m_filePath
).
baseName
());
result
=
CertificateError
;
}
delete
certificate
;
return
result
;
}
QString
S60CertificateInfo
::
errorString
()
const
{
return
m_errorString
.
isEmpty
()
?
m_certificate
->
errorString
()
:
m_errorString
;
}
quint32
S60CertificateInfo
::
capabilitiesSupported
()
{
return
NoInformation
;
}
QString
S60CertificateInfo
::
toHtml
()
{
const
QStringList
capabilityList
(
m_certificate
->
subjectInfo
(
QLatin1String
(
"1.2.826.0.1.1796587.1.1.1.6"
)));
QString
htmlString
;
QTextStream
str
(
&
htmlString
);
str
<<
"<html><body><table>"
<<
"<tr><td><b>"
<<
tr
(
"Type: "
)
<<
"</b></td>"
;
if
(
!
capabilityList
.
isEmpty
())
str
<<
"<td>"
<<
tr
(
"Developer certificate"
)
<<
"</td>"
;
if
(
m_certificate
->
isSelfSigned
())
str
<<
"<td>"
<<
tr
(
"Self signed certificate"
)
<<
"</td>"
;
str
<<
"</tr>"
;
QString
issuer
;
QStringList
issuerOrganizationList
(
m_certificate
->
issuerInfo
(
"X520.Organization"
));
if
(
!
issuerOrganizationList
.
isEmpty
())
issuer
=
issuerOrganizationList
.
join
(
QString
(
" "
));
QString
subject
;
QStringList
subjectOrganizationList
(
m_certificate
->
subjectInfo
(
"X520.Organization"
));
if
(
!
subjectOrganizationList
.
isEmpty
())
subject
=
subjectOrganizationList
.
join
(
QString
(
" "
));
QDateTime
startDate
(
m_certificate
->
startTime
().
toLocalTime
());
QDateTime
endDate
(
m_certificate
->
endTime
().
toLocalTime
());
str
<<
"<tr><td><b>"
<<
tr
(
"Issued by: "
)
<<
"</b></td><td>"
<<
issuer
<<
"</td></tr>"
<<
"<tr><td><b>"
<<
tr
(
"Issued to: "
)
<<
"</b></td><td>"
<<
subject
<<
"</td></tr>"
<<
"<tr><td><b>"
<<
tr
(
"Valid from: "
)
<<
"</b></td><td>"
<<
startDate
.
toString
(
QLatin1String
(
SIMPLE_DATE_FORMAT
))
<<
"</td></tr>"
<<
"<tr><td><b>"
<<
tr
(
"Valid to: "
)
<<
"</b></td><td>"
<<
endDate
.
toString
(
QLatin1String
(
SIMPLE_DATE_FORMAT
))
<<
"</td></tr>"
;
if
(
!
capabilityList
.
isEmpty
())
{
bool
isOk
(
false
);
quint32
capabilities
=
capabilityList
.
at
(
0
).
toLong
(
&
isOk
);
if
(
isOk
)
{
str
<<
"<tr><td><b>"
<<
tr
(
"Capabilities: "
)
<<
"</b></td><td>"
<<
createCapabilityList
(
capabilities
).
join
(
" "
)
<<
"</td></tr>"
;
}
}
const
QStringList
imeiList
(
m_certificate
->
subjectInfo
(
QLatin1String
(
"1.2.826.0.1.1796587.1.1.1.1"
)));
if
(
!
imeiList
.
isEmpty
())
{
QString
imeiListString
;
QString
space
(
" "
);
int
MAX_DISPLAYED_IMEI_COUNT
=
30
;
if
(
imeiList
.
count
()
>
MAX_DISPLAYED_IMEI_COUNT
)
{
//1000 items would be too much :)
for
(
int
i
=
0
;
i
<
MAX_DISPLAYED_IMEI_COUNT
;
++
i
)
imeiListString
+=
imeiList
.
at
(
i
)
+
space
;
imeiListString
.
replace
(
imeiListString
.
length
()
-
1
,
1
,
QString
(
"..."
));
}
else
imeiListString
=
imeiList
.
join
(
space
);
str
<<
"<tr><td><b>"
<<
tr
(
"Supporting %n device(s): "
,
""
,
imeiList
.
count
())
<<
"</b></td><td>"
<<
imeiListString
<<
"</td></tr>"
;
}
return
htmlString
;
}
src/plugins/qt4projectmanager/qt-s60/s60certificateinfo.h
View file @
993771f0
...
...
@@ -30,19 +30,60 @@
#ifndef S60CERTIFICATEINFO_H
#define S60CERTIFICATEINFO_H
#include
<QtCore/QObject>
#include
<QtCore/QtGlobal>
QT_FORWARD_DECLARE_CLASS
(
QString
)
QT_FORWARD_DECLARE_CLASS
(
S60SymbianCertificate
)
class
S60CertificateInfo
class
S60CertificateInfo
:
public
QObject
{
Q_OBJECT
public:
enum
CertificateState
{
CertificateValid
,
CertificateWarning
,
CertificateError
};
static
CertificateState
validateCertificate
(
const
QString
&
certFilePath
,
QString
*
errorString
=
0
);
enum
S60Capability
{
TCB
=
1
<<
(
31
-
0
),
CommDD
=
1
<<
(
31
-
1
),
PowerMgmt
=
1
<<
(
31
-
2
),
MultimediaDD
=
1
<<
(
31
-
3
),
ReadDeviceData
=
1
<<
(
31
-
4
),
WriteDeviceData
=
1
<<
(
31
-
5
),
DRM
=
1
<<
(
31
-
6
),
TrustedUI
=
1
<<
(
31
-
7
),
ProtServ
=
1
<<
(
31
-
8
),
DiskAdmin
=
1
<<
(
31
-
9
),
NetworkControl
=
1
<<
(
31
-
10
),
AllFiles
=
1
<<
(
31
-
11
),
SwEvent
=
1
<<
(
31
-
12
),
NetworkServices
=
1
<<
(
31
-
13
),
LocalServices
=
1
<<
(
31
-
14
),
ReadUserData
=
1
<<
(
31
-
15
),
WriteUserData
=
1
<<
(
31
-
16
),
Location
=
1
<<
(
31
-
17
),
SurroundingsDD
=
1
<<
(
31
-
18
),
UserEnvironment
=
1
<<
(
31
-
19
),
NoInformation
=
0
};
explicit
S60CertificateInfo
(
const
QString
&
filePath
,
QObject
*
parent
=
0
);
~
S60CertificateInfo
();
CertificateState
validateCertificate
();
quint32
capabilitiesSupported
();
QString
toHtml
();
QString
errorString
()
const
;
private:
S60SymbianCertificate
*
m_certificate
;
QString
m_filePath
;
QString
m_errorString
;
};
#endif // S60CERTIFICATEINFO_H
src/plugins/qt4projectmanager/qt-s60/s60createpackagestep.cpp
View file @
993771f0
...
...
@@ -469,20 +469,20 @@ bool S60CreatePackageStep::validateCustomSigningResources()
ProjectExplorer
::
Constants
::
TASK_CATEGORY_BUILDSYSTEM
));
return
false
;
}
S60CertificateInfo
::
CertificateState
certState
=
S60CertificateInfo
::
validateCertificate
(
customSignaturePath
(),
&
errorString
);
QScopedPointer
<
S60CertificateInfo
>
certInfoPtr
(
new
S60CertificateInfo
(
customSignaturePath
()));
S60CertificateInfo
::
CertificateState
certState
=
certInfoPtr
.
data
()
->
validateCertificate
(
);
switch
(
certState
)
{
case
S60CertificateInfo
::
CertificateError
:
emit
addOutput
(
errorString
,
BuildStep
::
ErrorMessageOutput
);
emit
addOutput
(
certInfoPtr
.
data
()
->
errorString
()
,
BuildStep
::
ErrorMessageOutput
);
emit
addTask
(
ProjectExplorer
::
Task
(
ProjectExplorer
::
Task
::
Error
,
errorString
,
certInfoPtr
.
data
()
->
errorString
()
,
QString
(),
-
1
,
ProjectExplorer
::
Constants
::
TASK_CATEGORY_BUILDSYSTEM
));
return
false
;
case
S60CertificateInfo
::
CertificateWarning
:
emit
addOutput
(
errorString
,
BuildStep
::
MessageOutput
);
emit
addOutput
(
certInfoPtr
.
data
()
->
errorString
()
,
BuildStep
::
MessageOutput
);
emit
addTask
(
ProjectExplorer
::
Task
(
ProjectExplorer
::
Task
::
Warning
,
errorString
,
certInfoPtr
.
data
()
->
errorString
()
,
QString
(),
-
1
,
ProjectExplorer
::
Constants
::
TASK_CATEGORY_BUILDSYSTEM
));
break
;
...
...
src/plugins/qt4projectmanager/qt-s60/s60symbiancertificate.cpp
View file @
993771f0
...
...
@@ -38,10 +38,275 @@
#include
<botan/bigint.h>
#include
<botan/oids.h>
#include
<botan/pem.h>
#include
<botan/sha160.h>
#include
<botan/oids.h>
#include
<botan/libstate.h>
#include
<botan/bit_ops.h>
#include
<algorithm>
#include
<memory>
using
namespace
Botan
;
namespace
{
const
char
*
const
CERT_IMEI_FIELD_NAME
=
"1.2.826.0.1.1796587.1.1.1.1"
;
const
char
*
const
CERT_CAPABILITY_FIELD_NAME
=
"1.2.826.0.1.1796587.1.1.1.6"
;
}
// ======== S60CertificateExtension
/*
* X.509 S60 Certificate Extension
*/
class
S60CertificateExtension
:
Certificate_Extension
{
public:
OID
oid_of
()
const
;
virtual
S60CertificateExtension
*
copy
()
const
=
0
;
virtual
~
S60CertificateExtension
()
{}
protected:
friend
class
S60Extensions
;
virtual
bool
should_encode
()
const
{
return
false
;
}
virtual
MemoryVector
<
byte
>
encode_inner
()
const
=
0
;
virtual
void
decode_inner
(
const
MemoryRegion
<
byte
>&
)
=
0
;
};
// ======== S60DeviceIdListConstraint
class
S60DeviceIdListConstraint
:
public
S60CertificateExtension
{
public:
S60CertificateExtension
*
copy
()
const
{
return
new
S60DeviceIdListConstraint
(
imei_list
);
}
S60DeviceIdListConstraint
()
{}
S60DeviceIdListConstraint
(
const
std
::
vector
<
ASN1_String
>&
o
)
:
imei_list
(
o
)
{}
std
::
vector
<
ASN1_String
>
get_imei_list
()
const
{
return
imei_list
;
}
private:
std
::
string
config_id
()
const
{
return
"deviceid_list_constraint"
;
}
std
::
string
oid_name
()
const
{
return
CERT_IMEI_FIELD_NAME
;
}
MemoryVector
<
byte
>
encode_inner
()
const
;
void
decode_inner
(
const
MemoryRegion
<
byte
>&
);
void
contents_to
(
Data_Store
&
,
Data_Store
&
)
const
;
std
::
vector
<
ASN1_String
>
imei_list
;
};
/*
* Encode the extension
*/
MemoryVector
<
byte
>
S60DeviceIdListConstraint
::
encode_inner
()
const
{
qFatal
(
"Encoding S60 extensions is not supported."
);
return
MemoryVector
<
byte
>
();
}
/*
* Decode the extension
*/
#include
"botan/hex.h"
void
S60DeviceIdListConstraint
::
decode_inner
(
const
MemoryRegion
<
byte
>&
in
)
{
BER_Decoder
(
in
)
.
start_cons
(
SEQUENCE
)
.
decode_list
(
imei_list
)
.
end_cons
();
}
/*
* Return a textual representation
*/
void
S60DeviceIdListConstraint
::
contents_to
(
Data_Store
&
subject
,
Data_Store
&
)
const
{
for
(
u32bit
j
=
0
;
j
!=
imei_list
.
size
();
++
j
)
subject
.
add
(
CERT_IMEI_FIELD_NAME
,
imei_list
[
j
].
value
());
}
// ======== S60CapabilityConstraint
class
S60CapabilityConstraint
:
public
S60CertificateExtension
{
public:
S60CertificateExtension
*
copy
()
const
{
return
new
S60CapabilityConstraint
(
capabilities
);
}
S60CapabilityConstraint
()
{}
S60CapabilityConstraint
(
const
SecureVector
<
byte
>&
o
)
:
capabilities
(
o
)
{}
SecureVector
<
byte
>
get_capability_list
()
const
{
return
capabilities
;
}
private:
std
::
string
config_id
()
const
{
return
"capability_constraint"
;
}
std
::
string
oid_name
()
const
{
return
"CERT_CAPABILITY_FIELD_NAME"
;
}
MemoryVector
<
byte
>
encode_inner
()
const
;
void
decode_inner
(
const
MemoryRegion
<
byte
>&
);
void
contents_to
(
Data_Store
&
,
Data_Store
&
)
const
;
SecureVector
<
byte
>
capabilities
;
};
/*
* Encode the extension
*/
MemoryVector
<
byte
>
S60CapabilityConstraint
::
encode_inner
()
const
{
qFatal
(
"Encoding S60 extensions is not supported."
);
return
MemoryVector
<
byte
>
();
}
/*
* Decode the extension
*/
void
S60CapabilityConstraint
::
decode_inner
(
const
MemoryRegion
<
byte
>&
in
)
{
BER_Decoder
(
in
)
.
decode
(
capabilities
,
BIT_STRING
)
.
verify_end
();
}
/*
* Return a textual representation
*/
void
S60CapabilityConstraint
::
contents_to
(
Data_Store
&
subject
,
Data_Store
&
)
const
{
quint32
capabilitiesValue
=
0
;
for
(
u32bit
j
=
0
;
j
!=
sizeof
(
quint32
);
++
j
)
{
quint32
capabilitie
(
capabilities
[
sizeof
(
quint32
)
-
1
-
j
]);
capabilitiesValue
|=
capabilitie
<<
8
*
j
;
}
subject
.
add
(
CERT_CAPABILITY_FIELD_NAME
,
capabilitiesValue
);
}
// ======== S60Extensions
class
S60Extensions
:
public
ASN1_Object
{
public:
void
encode_into
(
class
DER_Encoder
&
)
const
;
void
decode_from
(
class
BER_Decoder
&
);
void
contents_to
(
Data_Store
&
,
Data_Store
&
)
const
;
void
add
(
Certificate_Extension
*
extn
)
{
extensions
.
push_back
(
extn
);
}
S60Extensions
&
operator
=
(
const
S60Extensions
&
);
S60Extensions
(
const
S60Extensions
&
);
S60Extensions
(
bool
st
=
true
)
:
should_throw
(
st
)
{}
~
S60Extensions
();
private:
static
Certificate_Extension
*
get_extension
(
const
OID
&
);
std
::
vector
<
Certificate_Extension
*>
extensions
;
bool
should_throw
;
};
/*
* S60Extensions Copy Constructor
*/
S60Extensions
::
S60Extensions
(
const
S60Extensions
&
extensions
)
:
ASN1_Object
()
{
*
this
=
extensions
;
}
/*
* Extensions Assignment Operator
*/
S60Extensions
&
S60Extensions
::
operator
=
(
const
S60Extensions
&
other
)
{
for
(
u32bit
j
=
0
;
j
!=
extensions
.
size
();
++
j
)
delete
extensions
[
j
];
extensions
.
clear
();
for
(
u32bit
j
=
0
;
j
!=
other
.
extensions
.
size
();
++
j
)
extensions
.
push_back
(
other
.
extensions
[
j
]
->
copy
());
return
(
*
this
);
}
/*
* Return the OID of this extension
*/
OID
Certificate_Extension
::
oid_of
()
const
{
return
OIDS
::
lookup
(
oid_name
());
}
/*
* Encode an Extensions list
*/
void
S60Extensions
::
encode_into
(
DER_Encoder
&
to_object
)
const
{
Q_UNUSED
(
to_object
);
qFatal
(
"Encoding S60 extensions is not supported."
);
}
/*
* Decode a list of Extensions
*/
void
S60Extensions
::
decode_from
(
BER_Decoder
&
from_source
)
{
for
(
u32bit
j
=
0
;
j
!=
extensions
.
size
();
++
j
)
delete
extensions
[
j
];
extensions
.
clear
();
BER_Decoder
sequence
=
from_source
.
start_cons
(
SEQUENCE
);
while
(
sequence
.
more_items
())
{
OID
oid
;
MemoryVector
<
byte
>
value
;
bool
critical
;
sequence
.
start_cons
(
SEQUENCE
)
.
decode
(
oid
)
.
decode_optional
(
critical
,
BOOLEAN
,
UNIVERSAL
,
false
)
.
decode
(
value
,
OCTET_STRING
)
.
verify_end
()
.
end_cons
();
S60CertificateExtension
*
ext
=
0
;
if
(
OIDS
::
name_of
(
oid
,
CERT_IMEI_FIELD_NAME
))
ext
=
new
S60DeviceIdListConstraint
();
if
(
OIDS
::
name_of
(
oid
,
CERT_CAPABILITY_FIELD_NAME
))
ext
=
new
S60CapabilityConstraint
();
if
(
!
ext
)
{
if
(
!
critical
||
!
should_throw
)
continue
;
throw
Decoding_Error
(
"Encountered unknown X.509 extension marked "
"as critical; OID = "
+
oid
.
as_string
());
}
ext
->
decode_inner
(
value
);
extensions
.
push_back
(
ext
);
}
sequence
.
verify_end
();
}
/*
* Write the extensions to an info store
*/
void
S60Extensions
::
contents_to
(
Data_Store
&
subject_info
,
Data_Store
&
issuer_info
)
const
{
for
(
u32bit
j
=
0
;
j
!=
extensions
.
size
();
++
j
)
extensions
[
j
]
->
contents_to
(
subject_info
,
issuer_info
);
}
/*
* Delete an Extensions list
*/
S60Extensions
::~
S60Extensions
()
{
for
(
u32bit
j
=
0
;
j
!=
extensions
.
size
();
++
j
)
delete
extensions
[
j
];
}
// ======== S60SymbianCertificatePrivate
class
S60SymbianCertificatePrivate
:
private
Botan
::
X509_Object
...
...
@@ -242,6 +507,12 @@ void S60SymbianCertificatePrivate::force_decode()
if
(
v3_exts_data
.
type_tag
==
3
&&
v3_exts_data
.
class_tag
==
ASN1_Tag
(
CONSTRUCTED
|
CONTEXT_SPECIFIC
))
{
S60Extensions
s60extensions
(
false
);
BER_Decoder
(
v3_exts_data
.
value
).
decode
(
s60extensions
).
verify_end
();
s60extensions
.
contents_to
(
m_subject
,
m_issuer
);